Android 实例-个人理财工具 之三 添加账单页面A键字:android sdk1.0 sqlite intent ExpandableListActivit
Android 实例-个人理财工具 之三 添加账单页面A
键字:android sdk1.0 sqlite intent ExpandableListActivity SimpleCursorTreeAdapter cursor custom dialog
?
ColaBox 登记收支记录终于进入了复杂阶段了.这个界面我也是查找了很多资料以及打开android的源代码看了后才完成了,现在想来Google的开源真是明智的啊.
?
从前面的登录页面跳转进入添加账单页面.这个页面主要是用来登记收支记录的.
说白了就是往数据库录入明细.
?
表结构就是db.execSQL("CREATE TABLE bills ("
???????????????? + "_ID INTEGER PRIMARY KEY," //id
???????????????? + "fee integer,"???????????????????????????????????? //费用
???????????????? +"acctitemid integer,"????????????????????????? //账目类型
???????????????? + "userid integer,"??????????????????????????????? //使用者
???????????????? + "sdate TEXT,"???????????????????????????????? //日期
???????????????? + "stime TEXT,"??????????????????????????????? //时间
???????????????? + "desc TEXT"????????????????????????????????? //备注
???????????????? + ");");
?
可以看到主要是录入这些数据.首先是布置界面,我目前想到的用个tablelayout来布局
最后布局就是如下图这样
?
图1

?
在这儿我首先需要设置账目,前面我们已经初始化过账目的数据.
账目应该是一个ExpandableListActivity 2层的结构.需要从数据库里面读取.我在账目后面放了一个editview 只读没有光标的.也就是在这儿不可录入,在该editview的onclick事件里面我们打开账目选择界面.如下图
?
图2 账目选择

?
在这个界面中点击子节点就返回前面界面,把选择的账目传递过去.在这有个问题,如果用户需要录入的账目没有怎么办?
所以我这没有用dialog方式而是用了ExpandableListActivity? 在这个界面中如果长点某个子节点就弹出管理账目菜单,
来维护账目,如下图所示:
图3账目选择菜单示意????????????????????????????????????????????????????????????????????图4 编辑账目


?
?上面这些流程说起来很简单,可是当我用andriod编写时,遇到了很多问题,不过一个个都被我解决了,这正是编程的快乐所在.
关于ExpandableListActivity 大家可以参考android 里面apidemos 里面ExpandableList1,ExpandableList2,ExpandableList3
这里面对熟悉这个ui还是很有帮助的. 在ExpandableList2 里面就是从数据库进行读取的例子. 当然android里面那个我是没太
看明白因为他引用了import android.provider.Contacts.People; 联系人部分的框架,而我目前对数据库的操作和他不一样,我都是直接
sql访问.
但是你只要搞定2个cursor就ok了. Cursor groupCursor childCursor 其他都由SimpleCursorTreeAdapter帮你实现了.
下面我们来看看如何使用SimpleCursorTreeAdapter
?
??? }
???
??? public Cursor getChildenNode(String pid){
??? ?Log.v("cola","run getchildenNode");
?? ??return db.query("acctitem", new String[]{"_id", "name" }, "pid="+pid, null, null, null, "_id");???????? }只要这几步一个2级的tree list就可以出现了.
上面其实才是刚开始,后面我们需要使用一个自定义的Dialog 类似于一个inputBox 因为我们新增账目是需要输入账目的名称.
就是上面图4表现的.
虽然alertDialog提供了很多方法,可以选择list,treelist,radio, 可惜就是不能录入text.
这里我参考了api demos 里面的 DateWidgets1.java 和源代码里面DatePickerDialog.java .
我们可以从alertdialog 继承.然后添加一个Editview 最后把数据返回出来.只要把上面我说的2个java看清楚了后处理起来就简单了.
主要是一个回调函数的用法.下面看代码
//- public?class?Dialog_edit?extends?AlertDialog?implements?OnClickListener?{????private?String?text?=?"";
- ????private?EditText?edit;????private?OnDateSetListener?mCallback; //定义回调函数
- ????private?LinearLayout?layout;
- ????public?interface?OnDateSetListener?{? //回调接口
- ????????void?onDateSet(String?text);
- ????}
- ????protected?Dialog_edit(Context?context,?String?title,?String?value,????????????OnDateSetListener?Callback)?{
- ????????super(context);????????mCallback?=?Callback;
- ????????TextView?label?=?new?TextView(context);????????label.setText("hint");
- ????????//?setView(label); ????????edit?=?new?EditText(context);
- ????????edit.setText(value);????????layout?=?new?LinearLayout(context);
- ????????layout.setOrientation(LinearLayout.VERTICAL);????????//?LinearLayout.LayoutParams?param?=
- ????????//?new?LinearLayout.LayoutParams(100,?40); ????????//?layout.addView(label,?param);
- ????????LinearLayout.LayoutParams?param2?=?new?LinearLayout.LayoutParams(200,????????????????50);
- ????????layout.addView(edit,?param2);
- ?????? //添加edit????????setView(layout);
- ????????setTitle(title);????????setButton("确定",?this);
- ????????setButton2("取消",?(OnClickListener)?null);
- ????}
- ????public?void?onClick(DialogInterface?dialog,?int?which)?{????????//?Log.v("cola","U?click?which="+which);
- ????????text?=?edit.getText().toString();????????Log.v("cola",?"U?click?text="?+?text);
- ????????if?(mCallback?!=?null)????????????mCallback.onDateSet(text);? //使用回调返回录入的数据
- ????}
- }
这样我们就完成了自定义的dialog 我们可以使用它来新增和编辑账目. 对于账目的增删改就是sql的事情了
在这我又遇到一个问题就是我新增一个账目后如何来刷新界面,从而反映账目修改后的变化
在这我开始以为只要使用getExpandableListView().invalidate(); 就可以了,
因为我之前在ExpandableList1.java例子里面,使用它可以刷新界面.
在那个例子里面我修改了数组后调用该方法,界面就刷新了,而在这SimpleCursorTreeAdapter就行不通了,我想
应该只要刷新cursor应该就可以了,后来找到了notifyDataSetChanged 呵呵,果然可以了. 这样账目的录入和管理就搞定了.
?
下面给出目前最新的代码.
首先是账目管理
- package?com.cola.ui;
- import?android.app.AlertDialog;
- import?android.app.ExpandableListActivity;import?android.content.Context;
- import?android.content.DialogInterface;import?android.content.Intent;
- import?android.database.Cursor;import?android.os.Bundle;
- import?android.provider.Contacts.People;import?android.util.Log;
- import?android.view.ContextMenu;import?android.view.MenuItem;
- import?android.view.View;import?android.view.ContextMenu.ContextMenuInfo;
- import?android.widget.ExpandableListAdapter;import?android.widget.ExpandableListView;
- import?android.widget.SimpleCursorTreeAdapter;import?android.widget.TextView;
- import?android.widget.ExpandableListView.ExpandableListContextMenuInfo;
- /**?*?Demonstrates?expandable?lists?backed?by?Cursors
- ?*/public?class?Frm_Editacctitem?extends?ExpandableListActivity?{
- ????private?int?mGroupIdColumnIndex;
- ????private?String?mPhoneNumberProjection[]?=?new?String[]?{?People.Phones._ID,????????????People.Phones.NUMBER?};
- ????private?ExpandableListAdapter?mAdapter;
- ????BilldbHelper?billdb;
- ????Dialog_edit?newdialog;
- ????????
- ????private?ExpandableListContextMenuInfo?info;
- ????????
- ????@Override????public?void?onCreate(Bundle?savedInstanceState)?{
- ????????super.onCreate(savedInstanceState);????????setTitle("ColaBox-选择账目");
- ????????billdb?=?new?BilldbHelper(this);
- ????????//?Query?for?people ????????Cursor?groupCursor?=?billdb.getParentNode();
- ????????//?Cache?the?ID?column?index
- ????????mGroupIdColumnIndex?=?groupCursor.getColumnIndexOrThrow("_ID");????????//?Set?up?our?adapter
- ????????mAdapter?=?new?MyExpandableListAdapter(groupCursor,?this,????????????????android.R.layout.simple_expandable_list_item_1,
- ????????????????android.R.layout.simple_expandable_list_item_1,????????????????new?String[]?{?"NAME"?},?//?Name?for?group?layouts
- ????????????????new?int[]?{?android.R.id.text1?},?new?String[]?{?"NAME"?},?// ????????????????new?int[]?{?android.R.id.text1?});
- ????????setListAdapter(mAdapter);????????registerForContextMenu(getExpandableListView());
- ????}
- ????????@Override
- ????public?boolean?onChildClick(ExpandableListView?parent,?View?v,?int?groupPosition,?int?childPosition,?long?id)????{
- ????????Bundle?bundle?=?new?Bundle();????????bundle.putString("DataKey",?((TextView)v).getText().toString());//给bundle?写入数据
- ????????Intent?mIntent?=?new?Intent();????????mIntent.putExtras(bundle);
- ????????setResult(RESULT_OK,?mIntent);????????billdb.close();
- ????????finish();?
- ????????return?true;????????}
- ????@Override????public?void?onCreateContextMenu(ContextMenu?menu,?View?v,
- ????????????ContextMenuInfo?menuInfo)?{????????super.onCreateOptionsMenu(menu);
- ????????if?(ExpandableListView????????????????.getPackedPositionType(((ExpandableListContextMenuInfo)?menuInfo).packedPosition)?==?1)?{
- ????????????Log.v("cola",?"run?menu");????????????menu.setHeaderTitle("菜单");
- ????????????menu.add(0,?1,?0,?"新?增");????????????menu.add(0,?2,?0,?"删?除");
- ????????????menu.add(0,?3,?0,?"编?辑");????????}
- ????}
- ????@Override
- ????public?boolean?onContextItemSelected(MenuItem?item)?{????????info?=?(ExpandableListContextMenuInfo)?item.getMenuInfo();
- ????????if?(item.getItemId()?==?1)?{
- ????????????//?Log.v("cola","id"+info.id); ????????????newdialog?=?new?Dialog_edit(this,?"请输入新增账目的名称",?"",
- ????????????????????mDialogClick_new);????????????newdialog.show();
- ????????}?else?if?(item.getItemId()?==?2)?{????????????new?AlertDialog.Builder(this).setTitle("提示").setMessage("确定要删除'"+((TextView)info.targetView).getText().toString()+"'这个账目吗?")
- ????????????????????.setIcon(R.drawable.quit).setPositiveButton("确定",????????????????????????????new?DialogInterface.OnClickListener()?{
- ????????????????????????????????public?void?onClick(DialogInterface?dialog,????????????????????????????????????????int?whichButton)?{
- ????????????????????????????????????billdb.Acctitem_delitem((int)info.id);????????????????????????????????????updatedisplay();
- ????????????????????????????????}????????????????????????????}).setNegativeButton("取消",
- ????????????????????????????new?DialogInterface.OnClickListener()?{????????????????????????????????public?void?onClick(DialogInterface?dialog,
- ????????????????????????????????????????int?whichButton)?{????????????????????????????????????//?取消按钮事件
- ????????????????????????????????}????????????????????????????}).show();
- ????????}?else?if?(item.getItemId()?==?3)?{
- ????????????newdialog?=?new?Dialog_edit(this,?"请修改账目名称",????????????????????((TextView)?info.targetView).getText().toString(),
- ????????????????????mDialogClick_edit);????????????newdialog.show();
- ????????}
- ????????return?false;????}
- ????private?Dialog_edit.OnDateSetListener?mDialogClick_new?=?new?Dialog_edit.OnDateSetListener()?{
- ????????public?void?onDateSet(String?text)?{????????????Log.v("cola",?"new?acctitem");
- ????????????billdb.Acctitem_newitem(text,ExpandableListView.getPackedPositionGroup(info.packedPosition));????????????updatedisplay();
- ????????}
- ????};????
- ????private?Dialog_edit.OnDateSetListener?mDialogClick_edit?=?new?Dialog_edit.OnDateSetListener()?{????????public?void?onDateSet(String?text)?{????????????
- ????????????billdb.Acctitem_edititem(text,(int)info.id);????????????updatedisplay();
- ????????}
- ????};
- ????private?void?updatedisplay(){????????Log.v("cola",?"update?display");
- ????????((MyExpandableListAdapter)mAdapter).notifyDataSetChanged();
- ????}????
- ????public?class?MyExpandableListAdapter?extends?SimpleCursorTreeAdapter?{
- ????????public?MyExpandableListAdapter(Cursor?cursor,?Context?context,????????????????int?groupLayout,?int?childLayout,?String[]?groupFrom,
- ????????????????int[]?groupTo,?String[]?childrenFrom,?int[]?childrenTo)?{????????????super(context,?cursor,?groupLayout,?groupFrom,?groupTo,
- ????????????????????childLayout,?childrenFrom,?childrenTo);????????}
- ????????@Override
- ????????protected?Cursor?getChildrenCursor(Cursor?groupCursor)?{
- ????????????String?pid?=?groupCursor.getLong(mGroupIdColumnIndex)?+?"";????????????//?Log.v("cola","pid="+pid);
- ????????????return?billdb.getChildenNode(pid);
- ????????}
- ????????@Override????????public?long?getGroupId(int?groupPosition)?{
- ????????????//?Log.v("cola",?"getGroupId?"?+?groupPosition); ????????????Cursor?groupCursor?=?(Cursor)?getGroup(groupPosition);
- ????????????return?groupCursor.getLong(mGroupIdColumnIndex);????????}
- ????????@Override
- ????????public?long?getChildId(int?groupPosition,?int?childPosition)?{????????????//?Log.v("cola",?"getChildId?"?+?groupPosition?+?","?+
- ????????????//?childPosition); ????????????Cursor?childCursor?=?(Cursor)?getChild(groupPosition,?childPosition);
- ????????????return?childCursor.getLong(0);????????}
- ????}
- }
自定义对话框
- package?com.cola.ui;
- import?android.app.AlertDialog;
- import?android.content.Context;import?android.content.DialogInterface;
- import?android.content.DialogInterface.OnClickListener;import?android.util.Log;
- import?android.widget.EditText;import?android.widget.LinearLayout;
- import?android.widget.TextView;
- public?class?Dialog_edit?extends?AlertDialog?implements?OnClickListener?{
- ????private?String?text?=?"";????private?EditText?edit;
- ????private?OnDateSetListener?mCallback;
- ????private?LinearLayout?layout;
- ????public?interface?OnDateSetListener?{
- ????????void?onDateSet(String?text);????}
- ????protected?Dialog_edit(Context?context,?String?title,?String?value,
- ????????????OnDateSetListener?Callback)?{????????super(context);
- ????????mCallback?=?Callback;????????TextView?label?=?new?TextView(context);
- ????????label.setText("hint");????????//?setView(label);
- ????????edit?=?new?EditText(context);????????edit.setText(value);
- ????????layout?=?new?LinearLayout(context);????????layout.setOrientation(LinearLayout.VERTICAL);
- ????????//?LinearLayout.LayoutParams?param?= ????????//?new?LinearLayout.LayoutParams(100,?40);
- ????????//?layout.addView(label,?param); ????????LinearLayout.LayoutParams?param2?=?new?LinearLayout.LayoutParams(200,
- ????????????????50);????????layout.addView(edit,?param2);
- ????????setView(layout);????????setTitle(title);
- ????????setButton("确定",?this);????????setButton2("取消",?(OnClickListener)?null);
- ????}
- ????public?void?onClick(DialogInterface?dialog,?int?which)?{
- ????????//?Log.v("cola","U?click?which="+which); ????????text?=?edit.getText().toString();
- ????????Log.v("cola",?"U?click?text="?+?text);????????if?(mCallback?!=?null)
- ????????????mCallback.onDateSet(text);
- ????}
- }
数据库管理代码
package?com.cola.ui;- import?android.content.Context;
- import?android.database.Cursor;import?android.database.sqlite.SQLiteDatabase;
- import?android.util.Log;
- /**?*?Provides?access?to?a?database?of?notes.?Each?note?has?a?title,?the?note
- ?*?itself,?a?creation?date?and?a?modified?data.?*/
- public?class?BilldbHelper?{
- ????private?static?final?String?TAG?=?"Cola_BilldbHelper";
- ????private?static?final?String?DATABASE_NAME?=?"cola.db";????
- ????SQLiteDatabase?db;????Context?context;
- ????????BilldbHelper(Context?_context)?{
- ????????context=_context;????????db=context.openOrCreateDatabase(DATABASE_NAME,?0,?null);?
- ????????Log.v(TAG,"db?path="+db.getPath());????}
- ????????public?void?CreateTable_acctitem()?{
- ????????try{????????????db.execSQL("CREATE?TABLE?acctitem?("
- ????????????????????+?"_ID?INTEGER?PRIMARY?KEY,"????????????????????+?"PID?integer,"
- ????????????????????+?"NAME?TEXT"???????????????????????????????????+?");");
- ????????????Log.v("cola","Create?Table?acctitem?ok");????????}catch(Exception?e){
- ????????????Log.v("cola","Create?Table?acctitem?err,table?exists.");????????}
- ????}????
- ????public?void?CreateTable_bills()?{????????try{
- ????????????db.execSQL("CREATE?TABLE?bills?("????????????????????+?"_ID?INTEGER?PRIMARY?KEY,"
- ????????????????????+"?acctitemid?integer,"???????????????????????+?"fee?integer,"
- ????????????????????+?"userid?integer,"????????????????????+?"sdate?TEXT,"
- ????????????????????+?"stime?TEXT,"????????????????????+?"desc?TEXT"????????????????
- ????????????????????+?");");????????????
- ????????????Log.v("cola","Create?Table?acctitem?ok");????????}catch(Exception?e){
- ????????????Log.v("cola","Create?Table?acctitem?err,table?exists.");????????}
- ????}????
- ????public?void?CreateTable_colaconfig()?{????????try{
- ????????????db.execSQL("CREATE?TABLE?colaconfig?("????????????????????+?"_ID?INTEGER?PRIMARY?KEY,"
- ????????????????????+?"NAME?TEXT"????????????????????????????????+?");");
- ????????????Log.v("cola","Create?Table?colaconfig?ok");????????}catch(Exception?e){
- ????????????Log.v("cola","Create?Table?acctitem?err,table?exists.");????????}
- ????}????
- ????public?void?InitAcctitem()?{????????try{
- ??????????//s.getBytes(encoding); ??????????db.execSQL("insert?into?acctitem?values?(1,null,'收入')");
- ??????????db.execSQL("insert?into?acctitem?values?(2,1,'工资')");??????????db.execSQL("insert?into?acctitem?values?(9998,1,'其他')");
- ??????????db.execSQL("insert?into?acctitem?values?(0,null,'支出')");??????????db.execSQL("insert?into?acctitem?values?(3,0,'生活用品')");
- ??????????db.execSQL("insert?into?acctitem?values?(4,0,'水电煤气费')");??????????db.execSQL("insert?into?acctitem?values?(5,0,'汽油费')");
- ??????????db.execSQL("insert?into?acctitem?values?(9999,0,'其他')");??????????
- ??????????//db.execSQL("insert?into?bills?values(100,135,10000,'','','备注')"); ??????????Log.v("cola","insert?into?ok");?
- ????????}catch(Exception?e)????????{
- ????????????Log.v("cola","init?acctitem?e="+e.getMessage());????????}
- ????????????}
- ????public?void?Acctitem_newitem(String?text,int?type){????????
- ????????Cursor?c?=db.query("acctitem",?new?String[]{"max(_id)+1"},?"_id?is?not?null?and?_id<9998",?null,?null,?null,?null);????????c.moveToFirst();
- ????????int?maxid=c.getInt(0);??????????????String?sql="insert?into?acctitem?values?("+maxid+","+type+",'"+text+"')";
- ????????db.execSQL(sql);????????Log.v("cola","newitem?ok?text="+text+"?id="+type+"?sql="+sql);
- ????????????}
- ????????public?void?Acctitem_edititem(String?text,int?id){??????
- ????????db.execSQL("update?acctitem?set?name='"+text+"'?where?_id="+id);????????Log.v("cola","edititem?ok?text="+text+"?id="+id);
- ????}????
- ????public?void?Acctitem_delitem(int?id){????????
- ????????db.execSQL("delete?from?acctitem?where?_id="+id);????????Log.v("cola","delitem?ok?id="+id);
- ????}????
- ????public?void?QueryTable_acctitem(){????????
- ????}????
- ????public?void?FirstStart(){????????try{
- ????????????String?col[]?=?{"type",?"name"?};????????????Cursor?c?=db.query("sqlite_master",?col,?"name='colaconfig'",?null,?null,?null,?null);
- ????????????int?n=c.getCount();????????????if?(c.getCount()==0){
- ????????????????CreateTable_acctitem();????????????????CreateTable_colaconfig();
- ????????????????CreateTable_bills();????????????????InitAcctitem();?????????
- ????????????}???????????????????????//getTree();????????????
- ????????????Log.v("cola","c.getCount="+n+"");????????????????????
- ????????????????????}catch(Exception?e){
- ????????????Log.v("cola","e="+e.getMessage());????????}
- ????????????????
- ????}????
- ????????public?void?close(){
- ????????db.close();????}
- ????????public?Cursor?getParentNode(){
- ????????return?db.query("acctitem",?new?String[]{"_id",?"name"?},?"pid?is?null",?null,?null,?null,?"pid,_id");????????
- ????}????
- ????public?Cursor?getChildenNode(String?pid){????????Log.v("cola","run?getchildenNode");
- ????????return?db.query("acctitem",?new?String[]{"_id",?"name"?},?"pid="+pid,?null,?null,?null,?"_id");?????
- ????}???}
?
这段代码搞了2个通宵.昨天晚上又被ubuntu 8.04和vmware 5.5 折腾死.我的周末就这样泡汤了.
##############################################
2008-11-23 01:43 湖北武汉
?
?
?
##############################################
备注:
????? 今天看了下android的dialog例子,发现android 带了可输入文字的dialog例子,呵呵,实际上和我自定义的方法就是类似的.
我之前还是demo看的太少了,也就不会走弯路了.
????? 具体可以看AlertDialogSamples.java