【家庭记账本】Android开发(提交稿件)
本次更新了自己的app,这次更新是上交作业,还有很多预想功能没有实现,有时间还会继续更新。一些界面跟上次的没有差别,这里只展示新增的东西。
改进后的app使用了Fragment+底部导航栏;ListView显示数据;选择日期上使用了DatePickerDialog;最后增设了“删除数据”按钮,由于在限定时间内没有完成按条件模糊删除功能,所以这里删除是将数据库所有数据删除。接下来进行展示:
首先是添加数据界面的选择日期:
代码如下:
1 @Override 2 public void onClick(View view){ 3 switch (view.getId()){ 4 //点击日期的编辑框,弹出选择日期的界面 5 case R.id.amdate: 6 Calendar cal=Calendar.getInstance(); 7 //month要+1 8 DatePickerDialog date=new DatePickerDialog(AddMes.this, new DatePickerDialog.OnDateSetListener() { 9 @Override 10 public void onDateSet(DatePicker view, int year, int month, int dayOfMonth) { 11 //选择后显示 12 amdate.setText(year+"年"+(month+1)+"月"+dayOfMonth+"日"); 13 } 14 },cal.get(Calendar.YEAR),cal.get(Calendar.MONTH),cal.get(Calendar.DAY_OF_MONTH)+1); 15 date.show(); 16 break; 17 case R.id.amcreate: 18 user_str=amuser.getText().toString(); 19 name_str=amname.getText().toString(); 20 money_str=amoney.getText().toString()+"元"; 21 date_str=amdate.getText().toString(); 22 23 ContentValues values=new ContentValues(); 24 values.put("musername",user_str); 25 values.put("name",name_str); 26 values.put("money",money_str); 27 values.put("date",date_str); 28 values.put("inout",inout_str); 29 sqLiteDatabase.insert("message",null,values); 30 31 finish(); 32 break; 33 default: 34 break; 35 } 36 }
Android中的DatePickerDialog调用十分方便,编写时需要注意其中的month月份数要+1。为了弹出该选择界面,这里选择将日期的EditView框设置点击的监听事件。
接下来是Fragment+底部导航栏,这里写了很多文件。这些是Fragment的java文件,我一共设置了三个选项
详细文件:
FragmentA(只显示收入的账单)
1 package com.example.vacation; 2 3 import androidx.appcompat.app.AppCompatActivity; 4 import androidx.fragment.app.Fragment; 5 6 import android.database.Cursor; 7 import android.database.sqlite.SQLiteDatabase; 8 import android.os.Bundle; 9 import android.view.LayoutInflater; 10 import android.view.View; 11 import android.view.ViewGroup; 12 import android.widget.ListView; 13 import android.widget.TextView; 14 15 import java.util.ArrayList; 16 17 public class FragmentA extends Fragment { 18 private static String Aname; 19 private TextView atv_id,atv_name,atv_money,atv_date,atv_inout; 20 private ListView lv_mes1; 21 private SQLiteDatabase db; 22 private DBUser helper; 23 private ArrayList<MesInfo> listData; 24 private MesAdapter adapter; 25 public FragmentA(){ 26 } 27 @Override 28 public View onCreateView(LayoutInflater inflater, ViewGroup container,Bundle savedInstanceState){ 29 return inflater.inflate(R.layout.activity_fragment,container,false); 30 } 31 public void onActivityCreated(Bundle savedInstanceState){ 32 super.onActivityCreated(savedInstanceState); 33 Bundle bundle1=this.getArguments(); 34 if(bundle1!=null){ 35 Aname=bundle1.getString("Auser"); 36 } 37 atv_name=(TextView)getActivity().findViewById(R.id.tv_name); 38 atv_money=(TextView)getActivity().findViewById(R.id.tv_money); 39 atv_date=(TextView)getActivity().findViewById(R.id.tv_date); 40 atv_inout=(TextView)getActivity().findViewById(R.id.tv_inout); 41 lv_mes1=(ListView)getActivity().findViewById(R.id.lv_mes1); 42 listData=new ArrayList<MesInfo>(); 43 helper=new DBUser(getActivity(),"user_db",null,1); 44 db=helper.getWritableDatabase(); 45 46 String sql="select * from message where musername=? and inout='收入'"; 47 Cursor cursor=db.rawQuery(sql,new String[]{Aname}); 48 while(cursor.moveToNext()){ 49 MesInfo mes=new MesInfo(); 50 mes.setName(cursor.getString(cursor.getColumnIndex("name"))); 51 mes.setMoney(cursor.getString(cursor.getColumnIndex("money"))); 52 mes.setDate(cursor.getString(cursor.getColumnIndex("date"))); 53 mes.setInout(cursor.getString(cursor.getColumnIndex("inout"))); 54 listData.add(mes); 55 } 56 adapter=new MesAdapter(this.getActivity(),listData); 57 lv_mes1.setAdapter(adapter); 58 adapter.notifyDataSetChanged(); 59 } 60 }
粘贴时忘了代码注释(汗)
FragmentB(只显示支出的账单)
1 package com.example.vacation; 2 3 import androidx.appcompat.app.AppCompatActivity; 4 import androidx.fragment.app.Fragment; 5 6 import android.database.Cursor; 7 import android.database.sqlite.SQLiteDatabase; 8 import android.os.Bundle; 9 import android.view.LayoutInflater; 10 import android.view.View; 11 import android.view.ViewGroup; 12 import android.widget.ListView; 13 import android.widget.TextView; 14 15 import java.util.ArrayList; 16 17 public class FragmentB extends Fragment { 18 //声明控件 19 private static String Bname; 20 private TextView btv_id,btv_name,btv_money,btv_date,btv_inout; 21 private ListView lv_mes2; 22 private SQLiteDatabase db; 23 private DBUser helper; 24 private ArrayList<MesInfo> listData; 25 private MesAdapter adapter; 26 public FragmentB(){ 27 28 } 29 //连接对应fragment界面 30 @Override 31 public View onCreateView(LayoutInflater inflater, ViewGroup container,Bundle savedInstanceState){ 32 return inflater.inflate(R.layout.activity_fragment_b,container,false); 33 } 34 //编写事件 35 public void onActivityCreated(Bundle savedInstanceState){ 36 super.onActivityCreated(savedInstanceState); 37 //接收从Activity传过来的值 38 Bundle bundle2=this.getArguments(); 39 if(bundle2!=null){ 40 Bname=bundle2.getString("Buser"); 41 } 42 //运用ListView进行遍历数据库并输出 43 btv_name=(TextView)getActivity().findViewById(R.id.tv_name); 44 btv_money=(TextView)getActivity().findViewById(R.id.tv_money); 45 btv_date=(TextView)getActivity().findViewById(R.id.tv_date); 46 btv_inout=(TextView)getActivity().findViewById(R.id.tv_inout); 47 lv_mes2=(ListView)getActivity().findViewById(R.id.lv_mes2); 48 listData=new ArrayList<MesInfo>(); 49 helper=new DBUser(getActivity(),"user_db",null,1); 50 db=helper.getWritableDatabase(); 51 52 String sql="select * from message where musername=? and inout='支出'"; 53 Cursor cursor=db.rawQuery(sql,new String[]{Bname}); 54 while(cursor.moveToNext()){ 55 MesInfo mes=new MesInfo(); 56 mes.setName(cursor.getString(cursor.getColumnIndex("name"))); 57 mes.setMoney(cursor.getString(cursor.getColumnIndex("money"))); 58 mes.setDate(cursor.getString(cursor.getColumnIndex("date"))); 59 mes.setInout(cursor.getString(cursor.getColumnIndex("inout"))); 60 listData.add(mes); 61 } 62 adapter=new MesAdapter(this.getActivity(),listData); 63 lv_mes2.setAdapter(adapter); 64 adapter.notifyDataSetChanged(); 65 } 66 }
FragmentC(显示所有账单)
1 import androidx.fragment.app.Fragment; 2 3 import android.content.Intent; 4 import android.database.Cursor; 5 import android.database.sqlite.SQLiteDatabase; 6 import android.os.Bundle; 7 import android.view.LayoutInflater; 8 import android.view.View; 9 import android.view.ViewGroup; 10 import android.widget.ListView; 11 import android.widget.TextView; 12 13 import java.util.ArrayList; 14 15 public class FragmentC extends Fragment { 16 //声明控件 17 private static String Cname; 18 private TextView ctv_id,ctv_name,ctv_money,ctv_date,ctv_inout; 19 private ListView lv_mes3; 20 private SQLiteDatabase db; 21 private DBUser helper; 22 private ArrayList<MesInfo> listData; 23 private MesAdapter adapter; 24 25 public FragmentC(){ 26 } 27 @Override 28 public View onCreateView(LayoutInflater inflater, ViewGroup container,Bundle savedInstanceState){ 29 return inflater.inflate(R.layout.activity_fragment_c,container,false); 30 } 31 //事件 32 @Override 33 public void onActivityCreated(Bundle savedInstanceState){ 34 super.onActivityCreated(savedInstanceState); 35 Bundle bundle3=this.getArguments(); 36 if(bundle3!=null){ 37 Cname=bundle3.getString("Cuser"); 38 } 39 ctv_name=(TextView)getActivity().findViewById(R.id.tv_name); 40 ctv_money=(TextView)getActivity().findViewById(R.id.tv_money); 41 ctv_date=(TextView)getActivity().findViewById(R.id.tv_date); 42 ctv_inout=(TextView)getActivity().findViewById(R.id.tv_inout); 43 lv_mes3=(ListView)getActivity().findViewById(R.id.lv_mes3); 44 listData=new ArrayList<MesInfo>(); 45 helper=new DBUser(getActivity(),"user_db",null,1); 46 db=helper.getWritableDatabase(); 47 48 String sql="select * from message where musername=?"; 49 Cursor cursor=db.rawQuery(sql,new String[]{Cname}); 50 while(cursor.moveToNext()){ 51 MesInfo mes=new MesInfo(); 52 mes.setName(cursor.getString(cursor.getColumnIndex("name"))); 53 mes.setMoney(cursor.getString(cursor.getColumnIndex("money"))); 54 mes.setDate(cursor.getString(cursor.getColumnIndex("date"))); 55 mes.setInout(cursor.getString(cursor.getColumnIndex("inout"))); 56 listData.add(mes); 57 } 58 adapter=new MesAdapter(this.getActivity(),listData); 59 lv_mes3.setAdapter(adapter); 60 adapter.notifyDataSetChanged(); 61 } 62 }
fragment需要嵌入activity去实现,下面给出相关activity的代码
1 package com.example.vacation; 2 3 import androidx.appcompat.app.AppCompatActivity; 4 import androidx.fragment.app.FragmentManager; 5 import androidx.fragment.app.FragmentTransaction; 6 7 import android.content.Intent; 8 import android.os.Bundle; 9 import android.view.View; 10 import android.widget.RelativeLayout; 11 import android.widget.TextView; 12 13 public class Search extends AppCompatActivity implements View.OnClickListener{ 14 15 //声明,注意RelativeLayout也需要声明,此处用来嵌入fragment 16 private FragmentManager fragmentManager; 17 private RelativeLayout content; 18 private TextView item1,item2,item3; 19 private static String thename; 20 21 @Override 22 protected void onCreate(Bundle savedInstanceState) { 23 super.onCreate(savedInstanceState); 24 setContentView(R.layout.activity_search); 25 26 content=(RelativeLayout)findViewById(R.id.content); 27 item1=(TextView)findViewById(R.id.item1); 28 item2=(TextView)findViewById(R.id.item2); 29 item3=(TextView)findViewById(R.id.item3); 30 31 fragmentManager=getSupportFragmentManager(); 32 33 item1.setOnClickListener(this); 34 item2.setOnClickListener(this); 35 item3.setOnClickListener(this); 36 37 Intent intentdata=getIntent(); 38 String catchuser=intentdata.getStringExtra("buser"); 39 if(catchuser!=null){ 40 thename=catchuser; 41 } 42 } 43 44 //点击不同按钮跳转至不同的fragment 45 @Override 46 public void onClick(View v) { 47 switch(v.getId()){ 48 //Activity向Fragment传值,使用Bundle 49 case R.id.item1: 50 FragmentA fragmentA=new FragmentA(); 51 Bundle bundle1=new Bundle(); 52 bundle1.putString("Auser",thename); 53 fragmentA.setArguments(bundle1); 54 FragmentTransaction transaction1=fragmentManager.beginTransaction(); 55 transaction1.replace(R.id.content,fragmentA); 56 transaction1.commit(); 57 break; 58 case R.id.item2: 59 FragmentB fragmentB=new FragmentB(); 60 Bundle bundle2=new Bundle(); 61 bundle2.putString("Buser",thename); 62 fragmentB.setArguments(bundle2); 63 FragmentTransaction transaction2=fragmentManager.beginTransaction(); 64 transaction2.replace(R.id.content,fragmentB); 65 transaction2.commit(); 66 break; 67 case R.id.item3: 68 FragmentC fragmentC=new FragmentC(); 69 Bundle bundle3=new Bundle(); 70 bundle3.putString("Cuser",thename); 71 fragmentC.setArguments(bundle3); 72 FragmentTransaction transaction3=fragmentManager.beginTransaction(); 73 transaction3.replace(R.id.content,fragmentC); 74 transaction3.commit(); 75 break; 76 default: 77 break; 78 } 79 } 80 }
接下来是界面设计
分三个fragment的xml界面以及包含底部导航栏的xml界面。
activity_search.xml
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".Search" android:orientation="vertical"> //这个RelativeLayout用于嵌入Fragment,注意权值 <RelativeLayout android:id="@+id/content" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_weight="1" ></RelativeLayout> //设置底部导航栏,注意权值设置 <LinearLayout android:layout_width="match_parent" android:layout_height="60dp" android:orientation="horizontal" > <TextView android:id="@+id/item1" android:layout_width="match_parent" android:layout_height="40dp" android:layout_weight="1" android:text="收入" android:textSize="30dp" android:gravity="center" ></TextView> <TextView android:id="@+id/item2" android:layout_width="match_parent" android:layout_height="40dp" android:layout_weight="1" android:text="支出" android:textSize="30dp" android:gravity="center" ></TextView> <TextView android:id="@+id/item3" android:layout_width="match_parent" android:layout_height="40dp" android:layout_weight="1" android:text="总览" android:textSize="30dp" android:gravity="center" ></TextView> </LinearLayout> </LinearLayout>
预设置RelativeLayout,这个部分是用来显示Fragment画面的,设置权值weight为1。底部导航栏用LinearLayout设置即可
activity_fragment.xml(收入)
1 <?xml version="1.0" encoding="utf-8"?> 2 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" 3 xmlns:app="http://schemas.android.com/apk/res-auto" 4 xmlns:tools="http://schemas.android.com/tools" 5 android:layout_width="match_parent" 6 android:layout_height="match_parent" 7 android:gravity="center" 8 > 9 <TextView 10 android:layout_width="match_parent" 11 android:layout_height="match_parent" 12 android:text="收入" 13 android:textSize="30dp" 14 android:gravity="center_horizontal" 15 android:textColor="#000000" 16 ></TextView> 17 18 <ListView 19 android:id="@+id/lv_mes1" 20 android:layout_width="match_parent" 21 android:layout_height="wrap_content" 22 android:layout_marginTop="40dp" 23 android:layout_marginBottom="60dp" 24 ></ListView> 25 26 </RelativeLayout>
activity_fragment_b.xml(支出)
1 <?xml version="1.0" encoding="utf-8"?> 2 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" 3 xmlns:app="http://schemas.android.com/apk/res-auto" 4 xmlns:tools="http://schemas.android.com/tools" 5 android:layout_width="match_parent" 6 android:layout_height="match_parent" 7 tools:context=".FragmentB"> 8 9 <TextView 10 android:layout_width="match_parent" 11 android:layout_height="match_parent" 12 android:text="支出" 13 android:textSize="30dp" 14 android:gravity="center_horizontal" 15 android:textColor="#000000" 16 ></TextView> 17 18 <ListView 19 android:id="@+id/lv_mes2" 20 android:layout_width="match_parent" 21 android:layout_height="wrap_content" 22 android:layout_marginTop="40dp" 23 android:layout_marginBottom="60dp" 24 ></ListView> 25 26 </RelativeLayout>
activity_fragment_c.xml(总览)
1 <?xml version="1.0" encoding="utf-8"?> 2 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" 3 xmlns:app="http://schemas.android.com/apk/res-auto" 4 xmlns:tools="http://schemas.android.com/tools" 5 android:layout_width="match_parent" 6 android:layout_height="match_parent" 7 tools:context=".FragmentC"> 8 9 <TextView 10 android:layout_width="match_parent" 11 android:layout_height="match_parent" 12 android:text="总览" 13 android:textSize="30dp" 14 android:gravity="center_horizontal" 15 android:textColor="#000000" 16 ></TextView> 17 18 <ListView 19 android:id="@+id/lv_mes3" 20 android:layout_width="match_parent" 21 android:layout_height="wrap_content" 22 android:layout_marginTop="40dp" 23 android:layout_marginBottom="60dp" 24 ></ListView> 25 26 </RelativeLayout>
使用Fragment配合底部导航栏难度并不高,这种写法应用很广泛,至少这么写我可以避免页面跳转。显示数据也是使用ListView来实现。使用Fragment需要注意的是传值问题,一开始我想用intent进行传值,发现不可行,经过学习得知fragment传值需要节主bundle实现,当然还有其他方法,但这里没有写。
之后是ListView的应用展示,使用ListView需要适配器,而且应用时ListView的显示格式需要另设置xml文件。上面展示的fragment相关的xml代码已经调用了ListView控件,即:
1 <ListView 2 android:id="@+id/lv_mes1" 3 android:layout_width="match_parent" 4 android:layout_height="wrap_content" 5 android:layout_marginTop="40dp" 6 android:layout_marginBottom="60dp" 7 ></ListView>
ListView设置的格式文件如下:
list_item.xml
1 <?xml version="1.0" encoding="utf-8"?> 2 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 3 android:layout_width="match_parent" 4 android:layout_height="match_parent" 5 android:orientation="horizontal"> 6 <TextView 7 android:id="@+id/tv_name" 8 android:layout_width="0dp" 9 android:layout_height="wrap_content" 10 android:gravity="center_horizontal" 11 android:layout_weight="1" 12 android:hint="商品" 13 android:textSize="12dp" 14 android:textColor="#6666FF" 15 ></TextView> 16 17 <TextView 18 android:id="@+id/tv_money" 19 android:layout_width="0dp" 20 android:layout_height="wrap_content" 21 android:gravity="center_horizontal" 22 android:layout_weight="1" 23 android:hint="价格" 24 android:textSize="12dp" 25 android:textColor="#6666FF" 26 ></TextView> 27 28 <TextView 29 android:id="@+id/tv_date" 30 android:layout_width="0dp" 31 android:layout_height="wrap_content" 32 android:gravity="center_horizontal" 33 android:layout_weight="1" 34 android:hint="日期" 35 android:textSize="12dp" 36 android:textColor="#6666FF" 37 ></TextView> 38 39 <TextView 40 android:id="@+id/tv_inout" 41 android:layout_width="0dp" 42 android:layout_height="wrap_content" 43 android:gravity="center_horizontal" 44 android:layout_weight="1" 45 android:hint="收/支" 46 android:textSize="12dp" 47 android:textColor="#6666FF" 48 ></TextView> 49 50 </LinearLayout>
要实现ListView,还需要将它们“拼接”起来。
首先是Info类:
1 package com.example.vacation; 2 3 public class MesInfo { 4 private int Id; 5 private String Username; 6 private String Name; 7 private String Money; 8 private String Date; 9 private String Inout; 10 11 public int getId(){ 12 return Id; 13 } 14 public void setId(int id){ 15 Id=id; 16 } 17 public String getUsername(){ 18 return Username; 19 } 20 public void setUsername(String username){ 21 Username=username; 22 } 23 public String getName(){ 24 return Name; 25 } 26 public void setName(String name){ 27 Name=name; 28 } 29 public String getMoney(){ 30 return Money; 31 } 32 public void setMoney(String money){ 33 Money=money; 34 } 35 public String getDate(){ 36 return Date; 37 } 38 public void setDate(String date){ 39 Date=date; 40 } 41 public String getInout(){ 42 return Inout; 43 } 44 public void setInout(String inout){ 45 Inout=inout; 46 } 47 }
之后是adapter(拼接开始)
1 package com.example.vacation; 2 3 import android.content.Context; 4 import android.view.LayoutInflater; 5 import android.view.View; 6 import android.view.ViewGroup; 7 import android.widget.BaseAdapter; 8 import android.widget.TextView; 9 10 import androidx.recyclerview.widget.RecyclerView; 11 12 import java.util.ArrayList; 13 //适配器操作 14 public class MesAdapter extends BaseAdapter { 15 private Context context; 16 //创建列表 17 private ArrayList<MesInfo> listData; 18 19 public MesAdapter(Context context,ArrayList<MesInfo> listData){ 20 this.context=context; 21 this.listData=listData; 22 } 23 //必要步骤 24 @Override 25 public int getCount() { 26 return listData.size(); 27 } 28 29 @Override 30 public Object getItem(int position) { 31 return listData.get(position); 32 } 33 34 @Override 35 public long getItemId(int position) { 36 return position; 37 } 38 39 @Override 40 public View getView(int position, View convertView, ViewGroup parent) { 41 ViewHolder viewHolder=null; 42 if(convertView==null){ 43 LayoutInflater inflater=LayoutInflater.from(context); 44 //这里将ListView的格式xml文件名称写入,名字千万别写错,否则调用后显示的格式会发生错误 45 convertView=inflater.inflate(R.layout.list_item,null); 46 viewHolder=new ViewHolder(); 47 viewHolder.tv_name=(TextView)convertView.findViewById(R.id.tv_name); 48 viewHolder.tv_money=(TextView)convertView.findViewById(R.id.tv_money); 49 viewHolder.tv_date=(TextView)convertView.findViewById(R.id.tv_date); 50 viewHolder.tv_inout=(TextView)convertView.findViewById(R.id.tv_inout); 51 convertView.setTag(viewHolder); 52 } 53 viewHolder=(ViewHolder)convertView.getTag(); 54 MesInfo model=listData.get(position); 55 viewHolder.tv_name.setText(model.getName()); 56 viewHolder.tv_money.setText(model.getMoney()); 57 viewHolder.tv_date.setText(model.getDate()); 58 viewHolder.tv_inout.setText(model.getInout()); 59 return convertView; 60 } 61 62 } 63 class ViewHolder{ 64 public TextView tv_name; 65 public TextView tv_money; 66 public TextView tv_date; 67 public TextView tv_inout; 68 }
ListView的适配器操作有很多函数,但在Android Studio上编写继承时,编辑器会自动帮你列出,只要填充内容即可,需要注意的便是注释的地方,那里填写你所设计的ListView样式的xml文件,这样在调用时会按照你设置的xml格式来显示。
最后就是删除按钮,只是一个简单的监听事件:
case R.id.delete: //删除按钮 sqLiteDatabase.delete("message","musername=?",new String[]{searchname}); Toast.makeText(Work.this,"记入信息删除成功",Toast.LENGTH_SHORT).show(); break
;
看看效果:
删除成功。