生活管家app
健康生活方式App '健康管家'全方位管理健康 #生活技巧# #健康生活方式# #健康生活方式书籍# #健康生活方式app#
这篇文章给大家带来的是一款android的生活管家app实现。
主要实现功能及其要求:
1、个人收入支出的管理。主要完成收入管理、支出管理、类别管理、收入查询、支出查询、统计信息等功能。
2、实现每次进入应用需要进行密码输入,增强安全性。
3、其他功能可根据个人自己的想法添加。
4、系统界面美观,操作方便。
好了,根据这样的要求,您会想到开发一个怎样的app呢?快发挥您的想象能力和动手能力吧!
接下来,来看看博主的实现,先来看看实现的效果展示吧。。。
应该还可以吧,不算太丑。其中的统计和辅助工具就没有实现了,太耽误时间了,如果读者有兴趣,可自行完成。
项目源码下载地址:`点击下载地址
**作者:**IT_faquir
博客地址:http://blog.csdn.net/IT_faquir/article/details/51534408
重点内容
java代码块和布局文件目录结构:
重点来了,那就是实现它。来跟着博主一起来看看是怎么实现的吧。(只讲解一些重点部分)。
主函数,作为程序的入口,直接上代码:
public class MainActivity extends Activity { private SharedPreferences sp; private DatabaseUtils dbUtils; MyDialog mDialog; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); sp = getSharedPreferences("firstInit", Context.MODE_PRIVATE); getActionBar().hide(); mDialog = new MyDialog(this); initDatabase(); } //作为第一次使用,将会初始化数据库。 private void initDatabase() { // Boolean isFirst = sp.getBoolean("isFirst", true);// 用于得到是否为第一次使用此程序 if (sp.getBoolean("isFirst", true)) {// 第一次使用初始化数据库 String sql1 = "create table userInfo(id INTEGER PRIMARY KEY,name,age,phone,birth,address,password)"; String sql2 = "create table income(id INTEGER PRIMARY KEY,date,type,money MONEY,remark)"; String sql3 = "create table outlay(id INTEGER PRIMARY KEY,date,type,money MONEY,remark)"; String sql4 = "create table incomeType(id INTEGER PRIMARY KEY,type)"; String sql5 = "create table outlayType(id INTEGER PRIMARY KEY,type)"; dbUtils = new DatabaseUtils(this); dbUtils.openDatabase(); dbUtils.create(sql1); dbUtils.create(sql2); dbUtils.create(sql3); dbUtils.create(sql4); dbUtils.create(sql5); dbUtils.insert("insert into userInfo(id) values(1)"); dbUtils.insert("insert into incomeType(type) values('工资')"); dbUtils.insert("insert into incomeType(type) values('股票')"); dbUtils.insert("insert into outlayType(type) values('消费')"); dbUtils.closeDB(); sp.edit().putBoolean("isFirst", false).commit(); mDialog.showSetPswDialog(); } else { mDialog.showLoginDialog(null).setCancelable(false); dbUtils = new DatabaseUtils(this); dbUtils.openDatabase(); Cursor curson1 = dbUtils.query("select type from incomeType"); String[] s1 = new String[curson1.getCount()]; int count1 = 0; while (curson1.moveToNext()) { s1[count1] = curson1.getString(0); count1++; } curson1.close(); LifeButlerUtils.incomeType = s1; Cursor curson2 = dbUtils.query("select type from outlayType"); String[] s2 = new String[curson2.getCount()]; int count2 = 0; while (curson2.moveToNext()) { String s = curson2.getString(0); System.out.println("xiao:" + s); s2[count2] = s; count2++; } curson2.close(); dbUtils.closeDB(); LifeButlerUtils.outlayType = s2; } } public void incomeManagement(View v) { startActivity(MainActivity.this, IncomeManActivity.class); } public void outlayManagement(View v) { startActivity(MainActivity.this, OutlayManActivity.class); } //其他的按钮启动界面就不在重复展现了。 ... public void exitSys(View v) { this.finish(); System.exit(0); } //封装下启动界面的一个方法,以简化代码 private void startActivity(Context context, Class c) { Intent intent = new Intent(context, c); startActivity(intent); } }
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687从主函数中可以看出,此程序用到了sqlite本地数据库。同时SharedPreference也在程序中得到运用,用于存放一些简单的本地数据,作为是否为第一次使用应用程序的依据。还有就是启动activity方法的巧妙封装,这样可以大大减少代码量。
从代码中同时看到的,楼主用到了一个关于数据的操作的一个工具类DatabaseUtils。
看看DatabaseUtils这工具类的代码:
public class DatabaseUtils { public static final String DBNAME = "mydb.db"; private Context context; private SQLiteDatabase db; public DatabaseUtils(Context context) { this.context = context; } public void openDatabase() { db = context.openOrCreateDatabase(DBNAME, context.MODE_PRIVATE, null); } public void create(String sql) { db.beginTransaction(); db.execSQL(sql); db.setTransactionSuccessful(); db.endTransaction(); } public void insert(String sql) { db.beginTransaction(); db.execSQL(sql); db.setTransactionSuccessful(); db.endTransaction(); } //修改很删除也类似进行封装。 ... public Cursor query(String sql) { db.beginTransaction(); Cursor cursor = db.rawQuery(sql, null); db.setTransactionSuccessful(); db.endTransaction(); return cursor; } // 判断数据表是否存在 public boolean isExsit(String tableName) { boolean result = false; if (tableName == null) { return false; } Cursor cursor = null; try { String sql = "select count(*) as c from sqlite_master where type ='table' and name ='" + tableName.trim() + "' "; cursor = db.rawQuery(sql, null); if (cursor.moveToNext()) { int count = cursor.getInt(0); if (count > 0) { result = true; } } } catch (Exception e) { e.printStackTrace(); } return result; } //要记得使用完数据库要关闭它。 public void closeDB() { db.close(); } }
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263这个数据库工具类很简单,就是对一些增删改查操作的封装。主要传入sql语句进行执行。因此需要读者,有一点的sql语句基础。
再回到主类,会发现有个Dialog,用于进入应用时输入密码使用。
我们来看看吧:
MyDialog实现:
public Dialog showLoginDialog(final Intent intent) { View li = LayoutInflater.from(context).inflate(R.layout.dialog_layout, null); final Dialog dialog = new AlertDialog.Builder(context).create(); // dialog.setTitle("给自己起个名字吧!"); dialog.show(); dialog.getWindow().setContentView(li); // dialog.setCancelable(false);// 是对话框不能按返回键取消 dialog.setCanceledOnTouchOutside(false);// 使对话框不能按旁边取消 dialog.getWindow().clearFlags( WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM); et = (EditText) li.findViewById(R.id.login_psw); li.findViewById(R.id.dialog_bn_ok).setOnClickListener( new OnClickListener() { @Override public void onClick(View v) { String psw = null; String myPsw = et.getText().toString().trim(); dbUtils.openDatabase(); Cursor c = dbUtils .query("select password from userInfo where id = 1"); while (c.moveToNext()) { psw = c.getString(0).trim(); } dbUtils.closeDB(); if (!psw.equals(myPsw)) { Toast.makeText(context, "密码错误", 500).show(); } else { if (intent != null) { context.startActivity(intent); } else { dialog.cancel(); } } } }); return dialog; }
123456789101112131415161718192021222324252627282930313233343536373839对话框的实现,是不是和我们再那些书上看到的对话框不一样能,这里楼主用到了自定义对话框,对对话框布局进行填充。
LayoutInflater.from(context).inflate(R.layout.dialog_layout,null); dialog.getWindow().setContentView(li);12
这样实现出来的效果既美观,又可以更好的自我把控。
看到效果图就知道;
InComeManActivity:
用于收入管理类用于输入的录入
public class IncomeManActivity extends BaseActivity { private EditText et_date, et_money, et_remark; private Spinner sp_source; private boolean haveDate = false; private DatabaseUtils dbUtils; @Override protected void onCreate(Bundle savedInstanceState) { // TODO Auto-generated method stub super.onCreate(savedInstanceState); setContentView(R.layout.incomeman_layout); dbUtils = new DatabaseUtils(this); init(); } private void init() { et_date = (EditText) findViewById(R.id.income_date); sp_source = (Spinner) findViewById(R.id.income_source); et_money = (EditText) findViewById(R.id.income_money); et_remark = (EditText) findViewById(R.id.income_remark); dbUtils.openDatabase(); Cursor c = dbUtils.query("select type from incomeType"); String types[] = new String[c.getCount()]; int count = 0; while(c.moveToNext()){ types[count] = c.getString(0); count++; } dbUtils.closeDB(); LifeButlerUtils.incomeType = types; ArrayAdapter<String> aAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, types); sp_source.setAdapter(aAdapter); et_date.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { showDialog(); } }); } public void hand(View v) { String date = et_date.getText().toString().trim(); String type = sp_source.getSelectedItem().toString(); String money = et_money.getText().toString().trim(); String remark = et_remark.getText().toString().trim(); if (chackContent(money, remark) && haveDate) { System.out.println(date + type + money + remark); dbUtils.openDatabase(); dbUtils.insert("insert into income(date,type,money,remark) values('" + date + "','" + type + "','" + money + "','" + remark + "')"); dbUtils.closeDB(); toast("添加成功。"); } else { toast("请填写完整信息!"); } } public void back(View v) { this.finish(); } private boolean chackContent(String money, String remark) { if (money.length() > 0 && remark.length() > 0) return true; return false; } private void showDialog() { Dialog dialog = null; Calendar c = Calendar.getInstance(); dialog = new DatePickerDialog(this, new DatePickerDialog.OnDateSetListener() { public void onDateSet(DatePicker dp, int year, int month, int dayOfMonth) { haveDate = true; String mon = String.valueOf(month+1); if(mon.length() == 1){ mon = "0"+mon; } String day = String.valueOf(dayOfMonth); if(day.length() == 1){ day = "0"+day; } et_date.setText(year + "-" + mon + "-" + day); } }, c.get(Calendar.YEAR), // 传入年份 c.get(Calendar.MONTH), // 传入月份 c.get(Calendar.DAY_OF_MONTH) // 传入天数 ); dialog.show(); } }
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103工作流程:在界面录入信息后,点击按键保存,检查所填的信息是否完整,如果完整则保存信息到本地的sqlite数据库,否则不保存。我想,您看完代码应该就懂了。
还有个是支出的录入,基本上和这的实现,没什么区别,主要就是sql语句有所变化,就不在继续贴出了。
查询的实现:
再来看看查询吧,这里以收入的查询为例:
也许难度就在于那些勾选查询,如何才能很好的实现,代码量少,又灵活的代码呢?如果有几十个勾选的条件,那代码量想想就可怕。因此楼主做了一些巧妙的处理:
public class IncomeQueryActivity extends BaseActivity { private EditText et_dateS, et_dateE, et_moneyMin, et_moneyMax; private Spinner sp_source; private CheckBox check_type, check_date, check_money; private DatabaseUtils dbUtils; @Override protected void onCreate(Bundle savedInstanceState) { // TODO Auto-generated method stub super.onCreate(savedInstanceState); setContentView(R.layout.incomequery_layout); dbUtils = new DatabaseUtils(this); init(); } private void init() { check_type = (CheckBox) findViewById(R.id.check_income_source); check_date = (CheckBox) findViewById(R.id.check_income_date); check_money = (CheckBox) findViewById(R.id.check_income_money); sp_source = (Spinner) findViewById(R.id.income_query_source); et_dateS = (EditText) findViewById(R.id.income_query_time1); et_dateE = (EditText) findViewById(R.id.income_query_time2); et_moneyMin = (EditText) findViewById(R.id.income_query_money1); et_moneyMax = (EditText) findViewById(R.id.income_query_money2); et_dateS.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { showDialog(et_dateS); } }); et_dateE.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { showDialog(et_dateE); } }); ArrayAdapter<String> aAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, LifeButlerUtils.incomeType); sp_source.setAdapter(aAdapter); } public void query(View v) { Map<String, Boolean> map = new HashMap<String, Boolean>(); boolean have_type = check_type.isChecked(); boolean have_date = check_date.isChecked(); boolean have_money = check_money.isChecked(); map.put("type", have_type); map.put("date", have_date); map.put("money", have_money); String source = sp_source.getSelectedItem().toString(); String date1 = et_dateS.getText().toString().trim(); String date2 = et_dateE.getText().toString().trim(); String money1 = et_moneyMin.getText().toString().trim(); String money2 = et_moneyMax.getText().toString().trim(); StringBuilder sb = new StringBuilder(); boolean isFirst = true;// 是否为第一个where boolean haveWhere = false;// 处理是否有where 语句 boolean isOk = true;// 处理是否信息完整性 if (have_type == true) { sb.append("type = '" + source + "'"); isFirst = false; haveWhere = true; } if (have_date == true) { if (date1.length() > 0 && date2.length() > 0) { if (!isFirst) { sb.append(" and "); } sb.append("date >= '" + date1 + "'and date <= '" + date2 + "'"); } else { toast("请选择日期。"); isOk = false; } haveWhere = true; } if (have_money == true) { if (!isFirst) { sb.append(" and "); } sb.append("money >= '" + money1 + "' and date <= '" + money2 + "'"); haveWhere = true; } // 处理结果 if (isOk) { String sql = null; if (haveWhere) sql = "select * from income where " + sb.toString().trim(); else sql = "select * from income"; dbUtils.openDatabase(); Cursor c = dbUtils.query(sql); int cCount = c.getColumnCount(); StringBuilder data = new StringBuilder(); while (c.moveToNext()) { for (int i = 0; i < cCount; i++) { data.append(c.getString(i).trim() + " "); } data.append("\n"); } dbUtils.closeDB(); Intent intent = new Intent(IncomeQueryActivity.this, QueryResultActivity.class); intent.putExtra("data", data.toString()); intent.putExtra("operate", "income"); startActivity(intent); System.out.println(sql); } } public void back(View v) { this.finish(); } private void showDialog(final EditText et) { //日期对话框,和上相同 } }
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119由于是进行sql语句查询因此,需要生成一条满足条件的sql语句,有没找到那代码:
if (have_type == true) { sb.append("type = '" + source + "'"); isFirst = false; haveWhere = true; } if (have_date == true) { if (date1.length() > 0 && date2.length() > 0) { if (!isFirst) { sb.append(" and "); } sb.append("date >= '" + date1 + "'and date <= '" + date2 + "'"); } else { toast("请选择日期。"); isOk = false; } haveWhere = true; } if (have_money == true) { if (!isFirst) { sb.append(" and "); } sb.append("money >= '" + money1 + "' and date <= '" + money2 + "'"); haveWhere = true; }
123456789101112131415161718192021222324没错就是块代码,if语句配合StringBuilder,实现了sql语句的动态生成。
outlay的查询与此类似,不在叙述。
因此楼主总结出了一句话:我们要灵活的应对每件事,这样能有时能达到事半功倍的效果。
再来看看类别的管理
在对类别管理的实现中,楼主用到了ViewPager+ListView和PopMenu
public class CategoryActivity extends BaseActivity implements OnCheckedChangeListener, OnPageChangeListener { private ViewPager viewPager; private ArrayList<View> listView; private DatabaseUtils dbUtils; private ArrayAdapter<String> mAdapter1; private ArrayAdapter<String> mAdapter2; private RadioGroup radioGroup; private RadioButton rb1; private RadioButton rb2; @Override protected void onCreate(Bundle savedInstanceState) { // TODO Auto-generated method stub super.onCreate(savedInstanceState); setContentView(R.layout.category_layout); getActionBar().hide(); dbUtils = new DatabaseUtils(this); init(); } private void init() { dbUtils.openDatabase(); radioGroup = (RadioGroup) findViewById(R.id.novelty_rg); radioGroup.setOnCheckedChangeListener(this); rb1 = (RadioButton) findViewById(R.id.rb_income); rb2 = (RadioButton) findViewById(R.id.rb_outlay);; viewPager = (ViewPager) findViewById(R.id.cate_viewPager); viewPager.setOnPageChangeListener(this); listView = new ArrayList<View>(); View v1 = getLayoutInflater().inflate(R.layout.cate_tab_01, null); View v2 = getLayoutInflater().inflate(R.layout.cate_tab_02, null); initV1(v1); initV2(v2); listView.add(v1); listView.add(v2); viewPager.setCurrentItem(0); viewPager.setAdapter(new MyPagerAdapter()); } private void initV1(View v1) { final String type = "incomeType"; ListView list = (ListView) v1.findViewById(R.id.cate_list1); Button bn = (Button) v1.findViewById(R.id.addOne); final List<String> types = new ArrayList<String>(); Cursor c1 = dbUtils.query("select type from incomeType"); while (c1.moveToNext()) { String t = c1.getString(0); types.add(t); } mAdapter1 = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, types); list.setAdapter(mAdapter1); list.setOnItemLongClickListener(new OnItemLongClickListener() { @Override public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) { myPopMenu(view, types, "incomeType", position); return true; } }); bn.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { new MyDialog(CategoryActivity.this).showAddDialog(type, types, handler); } }); } private void initV2(View v2) { final String type = "outlayType"; ListView list = (ListView) v2.findViewById(R.id.cate_list2); Button bn = (Button) v2.findViewById(R.id.addOne); final List<String> types = new ArrayList<String>(); Cursor c1 = dbUtils.query("select type from outlayType"); while (c1.moveToNext()) { String t = c1.getString(0); types.add(t); } mAdapter2 = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, types); list.setAdapter(mAdapter2); list.setOnItemLongClickListener(new OnItemLongClickListener() { @Override public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) { myPopMenu(view, types, "outlayType", position); return true; } }); bn.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { new MyDialog(CategoryActivity.this).showAddDialog(type, types, handler); } }); } public void myPopMenu(View v, final List<String> types, final String tableName, final int position) { PopupMenu p = new PopupMenu(this, v); p.getMenuInflater().inflate(R.menu.menu, p.getMenu()); p.setOnMenuItemClickListener(new OnMenuItemClickListener() { @Override public boolean onMenuItemClick(MenuItem item) { int id = item.getItemId(); switch (id) { case R.id.del: dbUtils.openDatabase(); dbUtils.delete("delete from " + tableName + " where type = '" + types.get(position) + "'"); types.remove(position); if (tableName.equals("incomeType")) { handler.sendEmptyMessage(0x1); types.toArray(LifeButlerUtils.incomeType); } else { types.toArray(LifeButlerUtils.outlayType); handler.sendEmptyMessage(0x2); } dbUtils.closeDB(); break; } return true; } }); p.show(); } Handler handler = new Handler() { @Override public void handleMessage(Message msg) { super.handleMessage(msg); if (msg.what == 0x1) { mAdapter1.notifyDataSetChanged(); } else if (msg.what == 0x2) { mAdapter2.notifyDataSetChanged(); } } }; class MyPagerAdapter extends PagerAdapter { @Override public int getCount() { return listView.size(); } @Override public void destroyItem(ViewGroup container, int position, Object object) { container.removeView(listView.get(position)); } @Override public boolean isViewFromObject(View view, Object arg1) { return view == arg1; } @Override public Object instantiateItem(ViewGroup container, int position) { // position; container.addView(listView.get(position)); return listView.get(position); } } @Override public void finish() { // TODO Auto-generated method stub super.finish(); dbUtils.closeDB(); } @Override public void onCheckedChanged(RadioGroup group, int checkedId) { switch (checkedId) { case R.id.rb_income:// 选择校内 // setTabSelect(0);//显示校内资讯 viewPager.setCurrentItem(0);// 显示校内资讯 break; case R.id.rb_outlay:// 选择校外 // setTabSelect(1);//显示校外资讯 viewPager.setCurrentItem(1);// 显示校外资讯 break; default: break; } } @Override public void onPageScrollStateChanged(int arg0) { } @Override public void onPageScrolled(int arg0, float arg1, int arg2) { } @Override public void onPageSelected(int arg0) { switch (arg0) { case 0:// 第一页 rb1.setChecked(true); break; case 1:// 第二页 rb2.setChecked(true); break; default: break; } } }
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222这块代码相对有点多,是一个完整的代码。主要就是自定义的一个ListView的适配器MyAdapter,将从数据库中查询出来的数据展现出来,利用ViewPager分别显示了输入的类别管理和支出的类别管理。在每个list上可以长按进行删除,以及在最下角可以添加类别操作。
好了这应用大体的主要代码都给出了,有些功能自己看看源代码吧,不再给出。谢谢您的围观,源码的下载地址在文章的开头。
网址:生活管家app https://www.yuejiaxmz.com/news/view/149984
相关内容
记录数据 生活管家APP生活记账管家官方下载app
节能云管家app
手机数据管家app
健康管家app下载
数据管家热门app排行榜
环境数据管家app
数据管家APP下载安装
健管助手app
任务管理app下载