您的位置:首页 > 移动开发 > Android开发

Android个人理财工具实例之三:添加账单页面 上

2012-11-08 22:21 711 查看
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。

//首先要实现groupcursor就是父节点游标,这个其实就是我的acctitem表的   
    //select * from accitem where pid is null 的结果   
    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);   
    //然后我要实现childCursor    
    //其实就是select * from acctitem where id=pid 的结果   
    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);   
      }   
    protected Cursor getChildrenCursor(Cursor groupCursor) {   
       String pid = groupCursor.getLong(mGroupIdColumnIndex) + "";   
       // Log.v("cola","pid="+pid);   
       return billdb.getChildenNode(pid);   
      }   
    }   
    //我们看看Billdbhelper里面的cursor   
       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级的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");        
        }   
          
    }
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: