Anroid Studio开发

您所在的位置:网站首页 diaryms日记本导入安卓 Anroid Studio开发

Anroid Studio开发

2024-07-07 22:37| 来源: 网络整理| 查看: 265

最近刚看完了《第一行代码》这本书,趁着手热,写了一个日记本App,App虽然挺简单的,但对于一个刚学Android开发的小白来说,开发起来还是很艰难的,现在项目已经完成,在这里跟大家分享下,希望一起交流进步!

先上图,顺便介绍下功能: 这是登录界面,简洁明了,不多说了哈 这是登录之后的主界面,采用的是卡片式布局 这是编辑界面 当长按时日记右上方会出现复选框,选中点击删除按钮即可进行删除操作

好了,功能介绍完毕,下面介绍下主要的实现方法吧

LoignActivity(实现登录操作):

package com.example.a15711.diarypractice; import android.content.Intent; import android.content.SharedPreferences; import android.graphics.Color; import android.mainactivity.MainActivity; import android.os.Build; import android.preference.PreferenceManager; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.telephony.CellIdentityCdma; import android.texthod.HideReturnsTransformationMethod; import android.texthod.PasswordTransformationMethod; import android.view.View; import android.widget.Button; import android.widget.CheckBox; import android.widget.EditText; import android.widget.Toast; public class LoginActivity extends AppCompatActivity{ private SharedPreferences pref;//定义一个SharedPreferences对象 private SharedPreferences.Editor editor;//调用SharedPreferences对象的edit()方法来获取一个SharedPreferences.Editor对象,用以添加要保存的数据 private Button login;//登录按钮 private EditText adminEdit;//用户名输入框 private EditText passwordEdit;//密码输入框 private CheckBox savePassword;//是否保存密码复选框 private CheckBox showPassword;//显示或隐藏密码复选框 @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); //将背景图与状态栏融合到一起,只支持Android5.0以上的版本 if(Build.VERSION.SDK_INT>=21){ View decorView=getWindow().getDecorView(); //布局充满整个屏幕 decorView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN|View.SYSTEM_UI_FLAG_LAYOUT_STABLE); //设置状态栏为透明 getWindow().setStatusBarColor(Color.TRANSPARENT); } setContentView(R.layout.activity_login); //获取各组件或对象的实例 pref= PreferenceManager.getDefaultSharedPreferences(this); login=(Button)findViewById(R.id.login_button); adminEdit=(EditText)findViewById(R.id.admin); passwordEdit=(EditText)findViewById(R.id.password); savePassword=(CheckBox)findViewById(R.id.save_password); showPassword=(CheckBox)findViewById(R.id.show_password); //获取当前“是否保存密码”的状态 final boolean isSave=pref.getBoolean("save_password",false); //当“是否保存密码”勾选时,从SharedPreferences对象中读出保存的内容,并显示出来 if(isSave){ String account=pref.getString("account",""); String password=pref.getString("password",""); adminEdit.setText(account); passwordEdit.setText(password); //把光标移到文本末尾处 adminEdit.setSelection(adminEdit.getText().length()); passwordEdit.setSelection(passwordEdit.getText().length()); savePassword.setChecked(true); } //用户点击登录时的处理事件 login.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { //读出用户名和密码并判断是否正确 String account=adminEdit.getText().toString(); String password=passwordEdit.getText().toString(); //用户名和密码正确 if(account.equals("admin")&&password.equals("123456")){ editor=pref.edit(); //“是否保存密码”勾选 if(savePassword.isChecked()){ editor.putBoolean("save_password",true); editor.putString("account",account); editor.putString("password",password); } else{ editor.clear(); } //提交完成数据存储 editor.apply(); //显示登录成功并跳转到主界面活动 Toast.makeText(LoginActivity.this,"登录成功",Toast.LENGTH_SHORT).show(); Intent intent=new Intent(LoginActivity.this, MainActivity.class); startActivity(intent); //结束当前活动 finish(); } //用户名或密码错误 else{ Toast.makeText(LoginActivity.this,"登录失败,请重新输入!",Toast.LENGTH_SHORT).show(); } } }); //用户点击'显示密码'复选框 showPassword.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if(showPassword.isChecked()){ showOrHide(passwordEdit,true); }else{ showOrHide(passwordEdit,false); } } }); } //当用户离开活动时,检测是否勾选记住密码,若勾选则保存用户输入的用户名及密码 @Override protected void onDestroy() { super.onDestroy(); editor=pref.edit(); String account=adminEdit.getText().toString(); String password=passwordEdit.getText().toString(); if(savePassword.isChecked()){ editor.putBoolean("save_password",true); editor.putString("account",account); editor.putString("password",password); }else{ editor.clear(); } editor.apply(); } //显示或隐藏密码 private void showOrHide(EditText passwordEdit,boolean isShow){ //记住光标开始的位置 int pos = passwordEdit.getSelectionStart(); if(isShow){ passwordEdit.setTransformationMethod(HideReturnsTransformationMethod.getInstance()); }else{ passwordEdit.setTransformationMethod(PasswordTransformationMethod.getInstance()); } passwordEdit.setSelection(pos); } }

这个活动挺简单的,要注意的地方不多,一个是SharedPreferences ,用它来保存用户名和密码比较方便;另一个就是showOrHide方法,用它来实现显示或隐藏密码,这里初始密码为隐藏状态,需要在布局中密码属性中设置:android:password=“true”;

MainActivity:(日记展示界面)

package android.mainactivity; import android.app.AlertDialog; import android.content.DialogInterface; import android.content.Intent; import android.editactivity.EditActivity; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.support.v7.widget.GridLayoutManager; import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.RecyclerView; import android.view.View; import android.widget.Button; import android.widget.CheckBox; import android.widget.Toast; import com.example.a15711.diarypractice.R; import org.litepal.crud.DataSupport; import java.util.ArrayList; import java.util.HashMap; import java.util.List; public class MainActivity extends AppCompatActivity { //要删除的项的标志HashMap数组 HashMap str=new HashMap(); //设置是否在onStart中更新数据源的标志 private int update=0; //存储diary对象的数组 private List diaryList=new ArrayList(); //适配器 private diaryAdapter adapter; //是否处于多选删除状态 // 设置这个变量是为了让区分正常点击和多选删除时的点击事件 //以及长按状态时不再响应长按事件 private boolean isDeleteState=false; //网格布局管理器 GridLayoutManager gridLayoutManager=new GridLayoutManager(this,2); //线性布局管理器 LinearLayoutManager linearLayoutManager=new LinearLayoutManager(this); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); //从数据库中获取日记 diaryList= DataSupport.findAll(diary.class); RecyclerView recyclerView=(RecyclerView)findViewById(R.id.recycler_view); if(diaryList.size()>0){ //数据库中有日记记录,以网格布局展示 recyclerView.setLayoutManager(gridLayoutManager); }else{ //数据库中没有日记记录,用线性布局显示“无数据” recyclerView.setLayoutManager(linearLayoutManager); } //适配器的初始化,第一个参数传入数据源,第二个参数false表示正常状态;true表示多选删除状态 adapter=new diaryAdapter(diaryList,false); recyclerView.setAdapter(adapter); //初始化‘新建’和‘删除’按钮 Button build=(Button)findViewById(R.id.build_button); Button delete=(Button)findViewById(R.id.delete_button); //点击‘新建’按钮时,跳转到编辑日记的活动 build.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Intent intent=new Intent(MainActivity.this, EditActivity.class); intent.putExtra("diaryContent","");//传入日记内容,这里为空 intent.putExtra("signal",0);//传入‘新建’标志:0 startActivity(intent); } }); //点击‘删除按钮时,执行删除操作 delete.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { deleteSelections(); } }); //为RecyclerView添加点击事件响应和长按事件响应 recyclerView.addOnItemTouchListener(new RecyclerItemClickListener(this, recyclerView, new RecyclerItemClickListener.OnItemClickListener() { //点击事件响应 @Override public void onItemClick(View view, int position) { if(!isDeleteState&&diaryList.size()>0){ // 普通点击事件 diary mDiary=diaryList.get(position); String diaryContent=mDiary.getContent().toString(); String diaryTime=mDiary.getTime().toString(); Intent intent=new Intent(MainActivity.this,EditActivity.class); //传递内容 intent.putExtra("diaryContent",diaryContent); //传入修改标志1:表示修改原有日记内容 intent.putExtra("signal",1); startActivity(intent); }else if (diaryList.size()>0){ //长按进入多选状态后的点击事件 CheckBox checkBox = (CheckBox) view.findViewById(R.id.check_box); if (checkBox.isChecked()) { checkBox.setChecked(false); str.remove(position); } else { str.put(position,diaryAdapter.mDiaryList.get(position).getContent()); checkBox.setChecked(true); } } } @Override public void onItemLongClick(View view, int position) { // 长按事件 if(!isDeleteState&&diaryList.size()>0){ isDeleteState=true; str.clear(); //把当前选中的的复选框设置为选中状态 diaryAdapter.isSelected.put(position,true); //把所有的CheckBox显示出来 RecyclerView recyclerView=(RecyclerView)findViewById(R.id.recycler_view); //第二个参数为true表示长按进入多选删除状态时的适配器初始化 adapter=new diaryAdapter(diaryList,true); recyclerView.setAdapter(adapter); str.put(position,diaryAdapter.mDiaryList.get(position).getContent()); } } })); } //用户返回该活动时 @Override protected void onStart() { super.onStart(); isDeleteState=false; if(update==1){ diaryList.clear(); RecyclerView recyclerView=(RecyclerView)findViewById(R.id.recycler_view); List data=DataSupport.findAll(diary.class); for(diary mdiary:data){ diaryList.add(mdiary); } if(diaryList.size()>0){ recyclerView.setLayoutManager(gridLayoutManager); }else{ recyclerView.setLayoutManager(linearLayoutManager); } adapter=new diaryAdapter(diaryList,false); recyclerView.setAdapter(adapter); } } @Override protected void onStop() { super.onStop(); update=1;//更新数据源 } //执行删除的函数 private void deleteSelections() { AlertDialog.Builder builder = new AlertDialog.Builder(this); if (str.size()==0) { builder.setTitle("提示").setMessage("当前未选中项目").setPositiveButton("确认", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { RecyclerView recyclerView=(RecyclerView)findViewById(R.id.recycler_view); adapter=new diaryAdapter(diaryList,false); recyclerView.setAdapter(adapter); isDeleteState=false; str.clear(); } }).create().show(); } else { builder.setTitle("提示"); builder.setMessage("确认删除所选日记?"); builder.setPositiveButton("确认", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { for(int i:str.keySet()){ DataSupport.deleteAll(diary.class,"content=?",str.get(i)); } diaryList.clear(); List data=DataSupport.findAll(diary.class); for(diary mdiary:data){ diaryList.add(mdiary); } adapter.notifyDataSetChanged(); RecyclerView recyclerView=(RecyclerView)findViewById(R.id.recycler_view); if(diaryList.size()>0){ recyclerView.setLayoutManager(gridLayoutManager); }else{ recyclerView.setLayoutManager(linearLayoutManager); } adapter=new diaryAdapter(diaryList,false); recyclerView.setAdapter(adapter); isDeleteState=false; str.clear(); Toast.makeText(MainActivity.this,"删除成功!",Toast.LENGTH_SHORT).show(); } }); builder.setNegativeButton("取消", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { RecyclerView recyclerView=(RecyclerView)findViewById(R.id.recycler_view); adapter=new diaryAdapter(diaryList,false); recyclerView.setAdapter(adapter); isDeleteState=false; str.clear(); } }); builder.create().show(); } } }

diaryAdapter(适配器):

package android.mainactivity; import android.content.Context; import android.support.annotation.NonNull; import android.support.v7.widget.CardView; import android.support.v7.widget.RecyclerView; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.CheckBox; import android.widget.TextView; import com.example.a15711.diarypractice.R; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import java.util.List; /** * Created by 15711 on 2018/10/16. */ public class diaryAdapter extends RecyclerView.Adapter { private Boolean isDuoXuan;//是否多选的标志 private Context mContext;//上下文 public static List mDiaryList=new ArrayList();//数据项列 //键为RecyclerView中各子项的position,值为该位置复选框的选中状态 public static HashMap isSelected=new HashMap(); //这是有日记展示的Holder static class ViewHolder extends RecyclerView.ViewHolder{ CardView cardView; TextView diaryContent; TextView diaryTime; CheckBox checkBox; public ViewHolder(View view){ super(view); cardView=(CardView)view; diaryContent=(TextView)view.findViewById(R.id.diary_content); diaryTime=(TextView)view.findViewById(R.id.diary_time); checkBox=(CheckBox)view.findViewById(R.id.check_box); } } //这是无日记展示的Holder static class EmptyViewHolder extends RecyclerView.ViewHolder{ View empty_view; TextView textView; public EmptyViewHolder(View view){ super(view); empty_view=view; textView=(TextView)view.findViewById(R.id.empty_text); } } //适配器的构造函数 public diaryAdapter(List diaryList,boolean isDuoXuan){ mDiaryList=diaryList; this.isDuoXuan=isDuoXuan; } //数据源是否为空,为空返回-1 @Override public int getItemViewType(int position) { if(mDiaryList.size()0?mDiaryList.size():1; } }

RecyclerItemClickListener(RecyclerView的监听器类):

package android.mainactivity; import android.content.Context; import android.support.v7.widget.RecyclerView; import android.view.GestureDetector; import android.view.MotionEvent; import android.view.View; //为RecyclerView设置监听事件 public class RecyclerItemClickListener implements RecyclerView.OnItemTouchListener { public interface OnItemClickListener { void onItemClick(View view, int position); void onItemLongClick(View view, int position); } private OnItemClickListener mListener; private GestureDetector mGestureDetector; public RecyclerItemClickListener(Context context, final RecyclerView recyclerView, OnItemClickListener listener) { mListener = listener; mGestureDetector = new GestureDetector(context, new GestureDetector.SimpleOnGestureListener() { @Override public boolean onSingleTapUp(MotionEvent e) { return true; } @Override public void onLongPress(MotionEvent e) { View childView = recyclerView.findChildViewUnder(e.getX(), e.getY()); if (childView != null && mListener != null) { mListener.onItemLongClick(childView, recyclerView.getChildAdapterPosition(childView)); } } }); } @Override public boolean onInterceptTouchEvent(RecyclerView view, MotionEvent e) { View childView = view.findChildViewUnder(e.getX(), e.getY()); if (childView != null && mListener != null && mGestureDetector.onTouchEvent(e)) { mListener.onItemClick(childView, view.getChildAdapterPosition(childView)); } return false; } @Override public void onTouchEvent(RecyclerView view, MotionEvent motionEvent) { } @Override public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept) { } }

这个活动的实现要配合一个RecyclerView适配器和一个RecyclerView监听器,以对点击事件及长按事件进行监听和处理,相对来说比较复杂,但耐心看的话还是很容易理解的,对照注释相信大家都可以看懂,在这里我就不多说了

EditActivity(编辑界面):

package android.editactivity; import android.app.AlertDialog; import android.content.ContentValues; import android.content.DialogInterface; import android.content.Intent; import android.mainactivity.KeyboardUtils; import android.support.v7.app.ActionBar; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.support.v7.widget.Toolbar; import android.view.Menu; import android.view.MenuItem; import android.mainactivity.diary; import android.view.View; import android.widget.EditText; import com.example.a15711.diarypractice.R; import org.litepal.crud.DataSupport; import java.text.SimpleDateFormat; public class EditActivity extends AppCompatActivity { //接收上个活动传入的日记内容 private String diaryContent; //接收上个活动传入的标志 private int signal=0; //加载菜单 public boolean onCreateOptionsMenu(Menu menu){ getMenuInflater().inflate(R.menu.edit_toolbar,menu); return true; } //菜单项的点击事件 @Override public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { //点击保存 case R.id.save_button: { EditText editText=(EditText)findViewById(R.id.edit_content); String content=editText.getText().toString(); SimpleDateFormat sdf=new SimpleDateFormat("yyyy年MM月dd日"); String time=sdf.format(new java.util.Date()); diary mDiary=new diary(content,time); //点击’新建‘后编辑的内容就存储 if(signal==0) { mDiary.save(); //防止连续点击’存储‘按钮连续存储一样的内容 signal=3; } //更新原有内容的就只更新 else{ //防止连续点击’存储‘按钮连续存储一样的内容 signal=3; ContentValues values = new ContentValues(); values.put("time", mDiary.getTime().toString()); DataSupport.updateAll(diary.class,values,"content=?",diaryContent); values.put("content", mDiary.getContent().toString()); DataSupport.updateAll(diary.class,values,"content=?",diaryContent); } //隐藏光标并收起键盘 editText.setCursorVisible(false); KeyboardUtils.hideKeyboard(this); break; } //点击返回 case android.R.id.home:{ //已经保存的直接返回 if(signal==3){ finish(); } //未保存的提示是否保存 else{ AlertDialog.Builder builder = new AlertDialog.Builder(this); builder.setTitle(""); builder.setMessage("保存此次修改吗?"); builder.setPositiveButton("确认", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { EditText editText=(EditText)findViewById(R.id.edit_content); String content=editText.getText().toString(); SimpleDateFormat sdf=new SimpleDateFormat("yyyy年MM月dd日"); String time=sdf.format(new java.util.Date()); diary mDiary=new diary(content,time); if(signal==0){ mDiary.save(); }else{ ContentValues values = new ContentValues(); values.put("time", mDiary.getTime().toString()); DataSupport.updateAll(diary.class,values,"content=?",diaryContent); values.put("content", mDiary.getContent().toString()); DataSupport.updateAll(diary.class,values,"content=?",diaryContent); } finish(); } }); builder.setNegativeButton("取消", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { finish(); } }); builder.create().show(); } break; } default: } return true; } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_edit); //接收由MainActivity传来的日记信息 Intent intent=getIntent(); diaryContent=intent.getStringExtra("diaryContent"); signal=intent.getIntExtra("signal",0); Toolbar toolbar=(Toolbar)findViewById(R.id.edit_toolbar); toolbar.setTitle(""); setSupportActionBar(toolbar); ActionBar actionBar=getSupportActionBar(); if(actionBar!=null){ actionBar.setDisplayHomeAsUpEnabled(true); actionBar.setHomeAsUpIndicator(R.drawable.ic_back); } final EditText editText=(EditText)findViewById(R.id.edit_content); editText.setText(diaryContent); //光标放文本后面 editText.setSelection(editText.getText().length()); editText.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { editText.setCursorVisible(true); } }); } }

这个活动主要实现了保存和返回两个按钮的功能,结合注释和之前两个活动的介绍,相信你也能容易理解的

好了,内容也都介绍的差不多了,下面来总结一下这次开发的经验和教训吧。

讲真的在开发过程中,有好几次遇到不能解决的bug时,差点就放弃了,甚至会怀疑是不是代码诚心跟你作对,最后结果证明还是自己在跟自己作对,很多时候只是一些小的细节没有注意到,就可能导致很多匪夷所思的错误,所以思维一定要严谨!不能想当然,不然真的会吃很多苦头。

开发程序的时候一定要有思路,不能想到哪写到哪,那样的话很没有效率而且写出来的代码很乱,在写代码的过程中尽量做到多写注释,这样当你有问题回过头来找错误时会有很大帮助,不然的话你会无从找起,从而浪费更多时间和精力。

开发的过程的确很苦,但只要坚持还是可以成功的,当你的程序成功的跑起来的时候,相信你的内心一定是充满喜悦与满足的。

通过这次的练习我也发现了自己很多不足,包括调试代码找问题的能力,以及深入理解问题并想出解决办法的能力等等,这些都需要自己去提高。

谢谢浏览! 源代码下载



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3