Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> Android開發實例 >> Android個人理財工具實例之三:添加賬單頁面 上

Android個人理財工具實例之三:添加賬單頁面 上

編輯:Android開發實例

       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)這樣:

Android個人理財工具-添加賬單頁面布局

       在這兒我首先需要設置賬目,前面我們已經初始化過賬目的數據。

       賬目應該是一個ExpandableListActivity 2層的結構。需要從數據庫裡面讀取。我在賬目後面放了一個editview 只讀沒有光標的,也就是在這兒不可錄入,在該editview的onclick事件裡面我們打開賬目選擇界面。如下圖:

       圖2 賬目選擇:

Android個人理財工具-賬目選擇

       在這個界面中點擊子節點就返回前面界面,把選擇的賬目傳遞過去。在這有個問題,如果用戶需要錄入的賬目沒有怎麼辦?

       所以我這沒有用dialog方式而是用了ExpandableListActivity。在這個界面中如果長點某個子節點就彈出管理賬目菜單,來維護賬目,如下圖所示:

       圖3 賬目選擇菜單:

Android個人理財工具-賬目選擇菜單

       圖4 編輯賬目:

Android個人理財工具-編輯賬目

       上面這些流程說起來很簡單,可是當我用andriod編寫時,遇到了很多問題,不過一個個都被我解決了,這正是編程的快樂所在。

       關於ExpandableListActivity 大家可以參考android 裡面apidemos 裡面ExpandableList1、ExpandableList2、ExpandableList3。

       這裡面對熟悉這個ui還是很有幫助的。在ExpandableList2 裡面就是從數據庫進行讀取的例子。當然android裡面那個我是沒太看明白因為他引用了import android.provider.Contacts.People; 聯系人部分的框架,而我目前對數據庫的操作和他不一樣,我都是直接sql訪問。

       但是你只要搞定2個cursor就ok了,Cursor groupCursor childCursor ,其他都由SimpleCursorTreeAdapter幫你實現了。

       下面我們來看看如何使用SimpleCursorTreeAdapter。

Java代碼
  1. //首先要實現groupcursor就是父節點游標,這個其實就是我的acctitem表的   
  2. //select * from accitem where pid is null 的結果   
  3. Cursor groupCursor = billdb.getParentNode();   
  4.         // Cache the ID column index   
  5. mGroupIdColumnIndex = groupCursor.getColumnIndexOrThrow("_ID");   
  6.         // Set up our adapter   
  7. mAdapter = new MyExpandableListAdapter(groupCursor, this,       android.R.layout.simple_expandable_list_item_1,   
  8.     android.R.layout.simple_expandable_list_item_1,   
  9.         new String[] { "NAME" }, // Name for group layouts   
  10.         new int[] { android.R.id.text1 },    
  11.         new String[] { "NAME" }, //   
  12.         new int[] { android.R.id.text1 });   
  13. setListAdapter(mAdapter);   
  14. //然後我要實現childCursor    
  15. //其實就是select * from acctitem where id=pid 的結果   
  16. public class MyExpandableListAdapter extends SimpleCursorTreeAdapter {   
  17. public MyExpandableListAdapter(Cursor cursor, Context context,   
  18.                 int groupLayout, int childLayout, String[] groupFrom,   
  19.                 int[] groupTo, String[] childrenFrom, int[] childrenTo)   
  20.  {   
  21.             super(context, cursor, groupLayout, groupFrom, groupTo,   
  22.                     childLayout, childrenFrom, childrenTo);   
  23.   }   
  24. protected Cursor getChildrenCursor(Cursor groupCursor) {   
  25.    String pid = groupCursor.getLong(mGroupIdColumnIndex) + "";   
  26.    // Log.v("cola","pid="+pid);   
  27.    return billdb.getChildenNode(pid);   
  28.   }   
  29. }   
  30. //我們看看Billdbhelper裡面的cursor   
  31.    public Cursor getParentNode(){   
  32.      return db.query("acctitem", new String[]{"_id", "name" }, "pid is null", null, null, null, "pid,_id");        
  33.      
  34.     }   
  35.        
  36.     public Cursor getChildenNode(String pid){   
  37.      Log.v("cola","run getchildenNode");   
  38.      return db.query("acctitem", new String[]{"_id", "name" }, "pid="+pid, null, null, null, "_id");        
  39.     }   
  40. //只要這幾步一個2級的tree list就可以出現了.  

       上面其實才是剛開始,後面我們需要使用一個自定義的Dialog 類似於一個inputBox,因為我們新增賬目是需要輸入賬目的名稱。就是上面圖4表現的。

       雖然alertDialog提供了很多方法,可以選擇list、treelist、radio,可惜就是不能錄入text。

       這裡我參考了api demos 裡面的 DateWidgets1.java 和源代碼裡面DatePickerDialog.java 。

       我們可以從alertdialog 繼承,然後添加一個Editview 最後把數據返回出來。只要把上面我說的2個java看清楚了後處理起來就簡單了。

       主要是一個回調函數的用法。下面看代碼:

Java代碼
  1. //   
  2. public class Dialog_edit extends AlertDialog implements OnClickListener {   
  3.     private String text = "";   
  4.     private EditText edit;   
  5.     private OnDateSetListener mCallback; //定義回調函數   
  6.     private LinearLayout layout;   
  7.     public interface OnDateSetListener {  //回調接口   
  8.         void onDateSet(String text);   
  9.     }   
  10.     protected Dialog_edit(Context context, String title, String value,   
  11.             OnDateSetListener Callback) {   
  12.         super(context);   
  13.         mCallback = Callback;   
  14.         TextView label = new TextView(context);   
  15.         label.setText("hint");   
  16.         // setView(label);   
  17.         edit = new EditText(context);   
  18.         edit.setText(value);   
  19.         layout = new LinearLayout(context);   
  20.         layout.setOrientation(LinearLayout.VERTICAL);   
  21.         // LinearLayout.LayoutParams param =   
  22.         // new LinearLayout.LayoutParams(100, 40);   
  23.         // layout.addView(label, param);   
  24.         LinearLayout.LayoutParams param2 = new LinearLayout.LayoutParams(200,   
  25.                 50);   
  26.         layout.addView(edit, param2);   
  27.        //添加edit   
  28.         setView(layout);   
  29.         setTitle(title);   
  30.         setButton("確定", this);   
  31.         setButton2("取消", (OnClickListener) null);   
  32.     }   
  33.     public void onClick(DialogInterface dialog, int which) {   
  34.         // Log.v("cola","U click which="+which);   
  35.         text = edit.getText().toString();   
  36.         Log.v("cola", "U click text=" + text);   
  37.         if (mCallback != null)   
  38.             mCallback.onDateSet(text);  //使用回調返回錄入的數據   
  39.     }   
  40. }  

       這樣我們就完成了自定義的dialog 我們可以使用它來新增和編輯賬目。對於賬目的增刪改就是sql的事情了。

       在這我又遇到一個問題就是我新增一個賬目後如何來刷新界面,從而反映賬目修改後的變化。

       在這我開始以為只要使用getExpandableListView().invalidate(); 就可以了。

       因為我之前在ExpandableList1.java例子裡面,使用它可以刷新界面。

       在那個例子裡面我修改了數組後調用該方法,界面就刷新了,而在這SimpleCursorTreeAdapter就行不通了,我想

       應該只要刷新cursor應該就可以了,後來找到了notifyDataSetChanged,呵呵,果然可以了。 這樣賬目的錄入和管理就搞定了。

       下面給出目前最新的代碼。

       首先是賬目管理:

Java代碼
  1. package com.cola.ui;   
  2. import android.app.AlertDialog;   
  3. import android.app.ExpandableListActivity;   
  4. import android.content.Context;   
  5. import android.content.DialogInterface;   
  6. import android.content.Intent;   
  7. import android.database.Cursor;   
  8. import android.os.Bundle;   
  9. import android.provider.Contacts.People;   
  10. import android.util.Log;   
  11. import android.view.ContextMenu;   
  12. import android.view.MenuItem;   
  13. import android.view.View;   
  14. import android.view.ContextMenu.ContextMenuInfo;   
  15. import android.widget.ExpandableListAdapter;   
  16. import android.widget.ExpandableListView;   
  17. import android.widget.SimpleCursorTreeAdapter;   
  18. import android.widget.TextView;   
  19. import android.widget.ExpandableListView.ExpandableListContextMenuInfo;   
  20. /**  
  21.  * Demonstrates expandable lists backed by Cursors  
  22.  */  
  23. public class Frm_Editacctitem extends ExpandableListActivity {   
  24.     private int mGroupIdColumnIndex;   
  25.     private String mPhoneNumberProjection[] = new String[] { People.Phones._ID,   
  26.             People.Phones.NUMBER };   
  27.     private ExpandableListAdapter mAdapter;   
  28.     BilldbHelper billdb;   
  29.     Dialog_edit newdialog;   
  30.        
  31.        
  32.     private ExpandableListContextMenuInfo info;   
  33.        
  34.        
  35.     @Override  
  36.     public void onCreate(Bundle savedInstanceState) {   
  37.         super.onCreate(savedInstanceState);   
  38.         setTitle("ColaBox-選擇賬目");   
  39.         billdb = new BilldbHelper(this);   
  40.         // Query for people   
  41.         Cursor groupCursor = billdb.getParentNode();   
  42.         // Cache the ID column index   
  43.         mGroupIdColumnIndex = groupCursor.getColumnIndexOrThrow("_ID");   
  44.         // Set up our adapter   
  45.         mAdapter = new MyExpandableListAdapter(groupCursor, this,   
  46.                 android.R.layout.simple_expandable_list_item_1,   
  47.                 android.R.layout.simple_expandable_list_item_1,   
  48.                 new String[] { "NAME" }, // Name for group layouts   
  49.                 new int[] { android.R.id.text1 }, new String[] { "NAME" }, //   
  50.                 new int[] { android.R.id.text1 });   
  51.         setListAdapter(mAdapter);   
  52.         registerForContextMenu(getExpandableListView());   
  53.     }   
  54.        
  55.     @Override  
  56.     public boolean onChildClick(ExpandableListView parent, View v, int groupPosition, int childPosition, long id)   
  57.     {   
  58.         Bundle bundle = new Bundle();   
  59.         bundle.putString("DataKey", ((TextView)v).getText().toString());//給bundle 寫入數據   
  60.         Intent mIntent = new Intent();   
  61.         mIntent.putExtras(bundle);   
  62.         setResult(RESULT_OK, mIntent);   
  63.         billdb.close();   
  64.         finish();    
  65.         return true;       
  66.     }   
  67.     @Override  
  68.     public void onCreateContextMenu(ContextMenu menu, View v,   
  69.             ContextMenuInfo menuInfo) {   
  70.         super.onCreateOptionsMenu(menu);   
  71.         if (ExpandableListView   
  72.                 .getPackedPositionType(((ExpandableListContextMenuInfo) menuInfo).packedPosition) == 1) {   
  73.             Log.v("cola", "run menu");   
  74.             menu.setHeaderTitle("菜單");   
  75.             menu.add(0, 1, 0, "新 增");   
  76.             menu.add(0, 2, 0, "刪 除");   
  77.             menu.add(0, 3, 0, "編 輯");   
  78.         }   
  79.     }   
  80.     @Override  
  81.     public boolean onContextItemSelected(MenuItem item) {   
  82.         info = (ExpandableListContextMenuInfo) item.getMenuInfo();   
  83.         if (item.getItemId() == 1) {   
  84.             // Log.v("cola","id"+info.id);   
  85.             newdialog = new Dialog_edit(this, "請輸入新增賬目的名稱", "",   
  86.                     mDialogClick_new);   
  87.             newdialog.show();   
  88.         } else if (item.getItemId() == 2) {   
  89.             new AlertDialog.Builder(this).setTitle("提示").setMessage("確定要刪除'"+((TextView)info.targetView).getText().toString()+"'這個賬目嗎?")   
  90.                     .setIcon(R.drawable.quit).setPositiveButton("確定",   
  91.                             new DialogInterface.OnClickListener() {   
  92.                                 public void onClick(DialogInterface dialog,   
  93.                                         int whichButton) {   
  94.                                     billdb.Acctitem_delitem((int)info.id);   
  95.                                     updatedisplay();   
  96.                                 }   
  97.                             }).setNegativeButton("取消",   
  98.                             new DialogInterface.OnClickListener() {   
  99.                                 public void onClick(DialogInterface dialog,   
  100.                                         int whichButton) {   
  101.                                     // 取消按鈕事件   
  102.                                 }   
  103.                             }).show();   
  104.         } else if (item.getItemId() == 3) {   
  105.             newdialog = new Dialog_edit(this, "請修改賬目名稱",   
  106.                     ((TextView) info.targetView).getText().toString(),   
  107.                     mDialogClick_edit);   
  108.             newdialog.show();   
  109.         }   
  110.         return false;   
  111.     }   
  112.     private Dialog_edit.OnDateSetListener mDialogClick_new = new Dialog_edit.OnDateSetListener() {   
  113.         public void onDateSet(String text) {   
  114.             Log.v("cola", "new acctitem");   
  115.             billdb.Acctitem_newitem(text,ExpandableListView.getPackedPositionGroup(info.packedPosition));   
  116.             updatedisplay();   
  117.         }   
  118.     };   
  119.        
  120.     private Dialog_edit.OnDateSetListener mDialogClick_edit = new Dialog_edit.OnDateSetListener() {   
  121.         public void onDateSet(String text) {               
  122.             billdb.Acctitem_edititem(text,(int)info.id);   
  123.             updatedisplay();   
  124.         }   
  125.     };   
  126.     private void updatedisplay(){   
  127.         Log.v("cola", "update display");   
  128.         ((MyExpandableListAdapter)mAdapter).notifyDataSetChanged();   
  129.     }   
  130.        
  131.     public class MyExpandableListAdapter extends SimpleCursorTreeAdapter {   
  132.         public MyExpandableListAdapter(Cursor cursor, Context context,   
  133.                 int groupLayout, int childLayout, String[] groupFrom,   
  134.                 int[] groupTo, String[] childrenFrom, int[] childrenTo) {   
  135.             super(context, cursor, groupLayout, groupFrom, groupTo,   
  136.                     childLayout, childrenFrom, childrenTo);   
  137.         }   
  138.         @Override  
  139.         protected Cursor getChildrenCursor(Cursor groupCursor) {   
  140.             String pid = groupCursor.getLong(mGroupIdColumnIndex) + "";   
  141.             // Log.v("cola","pid="+pid);   
  142.             return billdb.getChildenNode(pid);   
  143.         }   
  144.         @Override  
  145.         public long getGroupId(int groupPosition) {   
  146.             // Log.v("cola", "getGroupId " + groupPosition);   
  147.             Cursor groupCursor = (Cursor) getGroup(groupPosition);   
  148.             return groupCursor.getLong(mGroupIdColumnIndex);   
  149.         }   
  150.         @Override  
  151.         public long getChildId(int groupPosition, int childPosition) {   
  152.             // Log.v("cola", "getChildId " + groupPosition + "," +   
  153.             // childPosition);   
  154.             Cursor childCursor = (Cursor) getChild(groupPosition, childPosition);   
  155.             return childCursor.getLong(0);   
  156.         }   
  157.     }   
  158. }  

       自定義對話框:

Java代碼
  1. package com.cola.ui;   
  2. import android.app.AlertDialog;   
  3. import android.content.Context;   
  4. import android.content.DialogInterface;   
  5. import android.content.DialogInterface.OnClickListener;   
  6. import android.util.Log;   
  7. import android.widget.EditText;   
  8. import android.widget.LinearLayout;   
  9. import android.widget.TextView;   
  10. public class Dialog_edit extends AlertDialog implements OnClickListener {   
  11.     private String text = "";   
  12.     private EditText edit;   
  13.     private OnDateSetListener mCallback;   
  14.     private LinearLayout layout;   
  15.     public interface OnDateSetListener {   
  16.         void onDateSet(String text);   
  17.     }   
  18.     protected Dialog_edit(Context context, String title, String value,   
  19.             OnDateSetListener Callback) {   
  20.         super(context);   
  21.         mCallback = Callback;   
  22.         TextView label = new TextView(context);   
  23.         label.setText("hint");   
  24.         // setView(label);   
  25.         edit = new EditText(context);   
  26.         edit.setText(value);   
  27.         layout = new LinearLayout(context);   
  28.         layout.setOrientation(LinearLayout.VERTICAL);   
  29.         // LinearLayout.LayoutParams param =   
  30.         // new LinearLayout.LayoutParams(100, 40);   
  31.         // layout.addView(label, param);   
  32.         LinearLayout.LayoutParams param2 = new LinearLayout.LayoutParams(200,   
  33.                 50);   
  34.         layout.addView(edit, param2);   
  35.         setView(layout);   
  36.         setTitle(title);   
  37.         setButton("確定", this);   
  38.         setButton2("取消", (OnClickListener) null);   
  39.     }   
  40.     public void onClick(DialogInterface dialog, int which) {   
  41.         // Log.v("cola","U click which="+which);   
  42.         text = edit.getText().toString();   
  43.         Log.v("cola", "U click text=" + text);   
  44.         if (mCallback != null)   
  45.             mCallback.onDateSet(text);   
  46.     }   
  47. }   

       數據庫管理代碼:

Java代碼
  1. package com.cola.ui;   
  2. import android.content.Context;   
  3. import android.database.Cursor;   
  4. import android.database.sqlite.SQLiteDatabase;   
  5. import android.util.Log;   
  6. /**  
  7.  * Provides access to a database of notes. Each note has a title, the note  
  8.  * itself, a creation date and a modified data.  
  9.  */  
  10. public class BilldbHelper {   
  11.     private static final String TAG = "Cola_BilldbHelper";   
  12.     private static final String DATABASE_NAME = "cola.db";   
  13.        
  14.     SQLiteDatabase db;   
  15.     Context context;   
  16.        
  17.     BilldbHelper(Context _context) {   
  18.         context=_context;   
  19.         db=context.openOrCreateDatabase(DATABASE_NAME, 0, null);    
  20.         Log.v(TAG,"db path="+db.getPath());   
  21.     }   
  22.        
  23.     public void CreateTable_acctitem() {   
  24.         try{   
  25.             db.execSQL("CREATE TABLE acctitem ("  
  26.                     + "_ID INTEGER PRIMARY KEY,"  
  27.                     + "PID integer,"  
  28.                     + "NAME TEXT"                  
  29.                     + ");");   
  30.             Log.v("cola","Create Table acctitem ok");   
  31.         }catch(Exception e){   
  32.             Log.v("cola","Create Table acctitem err,table exists.");   
  33.         }   
  34.     }   
  35.        
  36.     public void CreateTable_bills() {   
  37.         try{   
  38.             db.execSQL("CREATE TABLE bills ("  
  39.                     + "_ID INTEGER PRIMARY KEY,"  
  40.                     +" acctitemid integer,"      
  41.                     + "fee integer,"  
  42.                     + "userid integer,"  
  43.                     + "sdate TEXT,"  
  44.                     + "stime TEXT,"  
  45.                     + "desc TEXT"                   
  46.                     + ");");   
  47.                
  48.             Log.v("cola","Create Table acctitem ok");   
  49.         }catch(Exception e){   
  50.             Log.v("cola","Create Table acctitem err,table exists.");   
  51.         }   
  52.     }   
  53.        
  54.     public void CreateTable_colaconfig() {   
  55.         try{   
  56.             db.execSQL("CREATE TABLE colaconfig ("  
  57.                     + "_ID INTEGER PRIMARY KEY,"  
  58.                     + "NAME TEXT"               
  59.                     + ");");   
  60.             Log.v("cola","Create Table colaconfig ok");   
  61.         }catch(Exception e){   
  62.             Log.v("cola","Create Table acctitem err,table exists.");   
  63.         }   
  64.     }   
  65.        
  66.     public void InitAcctitem() {   
  67.         try{   
  68.           //s.getBytes(encoding);   
  69.           db.execSQL("insert into acctitem values (1,null,'收入')");   
  70.           db.execSQL("insert into acctitem values (2,1,'工資')");   
  71.           db.execSQL("insert into acctitem values (9998,1,'其他')");   
  72.           db.execSQL("insert into acctitem values (0,null,'支出')");   
  73.           db.execSQL("insert into acctitem values (3,0,'生活用品')");   
  74.           db.execSQL("insert into acctitem values (4,0,'水電煤氣費')");   
  75.           db.execSQL("insert into acctitem values (5,0,'汽油費')");   
  76.           db.execSQL("insert into acctitem values (9999,0,'其他')");   
  77.              
  78.           //db.execSQL("insert into bills values(100,135,10000,'','','備注')");   
  79.           Log.v("cola","insert into ok");    
  80.         }catch(Exception e)   
  81.         {   
  82.             Log.v("cola","init acctitem e="+e.getMessage());   
  83.         }   
  84.            
  85.     }   
  86.     public void Acctitem_newitem(String text,int type){   
  87.            
  88.         Cursor c =db.query("acctitem", new String[]{"max(_id)+1"}, "_id is not null and _id<9998", null, null, null, null);   
  89.         c.moveToFirst();   
  90.         int maxid=c.getInt(0);         
  91.         String sql="insert into acctitem values ("+maxid+","+type+",'"+text+"')";   
  92.         db.execSQL(sql);   
  93.         Log.v("cola","newitem ok text="+text+" id="+type+" sql="+sql);   
  94.            
  95.     }   
  96.        
  97.     public void Acctitem_edititem(String text,int id){         
  98.         db.execSQL("update acctitem set name='"+text+"' where _id="+id);   
  99.         Log.v("cola","edititem ok text="+text+" id="+id);   
  100.     }   
  101.        
  102.     public void Acctitem_delitem(int id){   
  103.            
  104.         db.execSQL("delete from acctitem where _id="+id);   
  105.         Log.v("cola","delitem ok id="+id);   
  106.     }   
  107.        
  108.     public void QueryTable_acctitem(){   
  109.            
  110.     }   
  111.        
  112.     public void FirstStart(){   
  113.         try{   
  114.             String col[] = {"type", "name" };   
  115.             Cursor c =db.query("sqlite_master", col, "name='colaconfig'", null, null, null, null);   
  116.             int n=c.getCount();   
  117.             if (c.getCount()==0){   
  118.                 CreateTable_acctitem();   
  119.                 CreateTable_colaconfig();   
  120.                 CreateTable_bills();   
  121.                 InitAcctitem();            
  122.             }              
  123.             //getTree();               
  124.             Log.v("cola","c.getCount="+n+"");   
  125.                        
  126.                
  127.         }catch(Exception e){   
  128.             Log.v("cola","e="+e.getMessage());   
  129.         }   
  130.            
  131.            
  132.     }   
  133.        
  134.        
  135.     public void close(){   
  136.         db.close();   
  137.     }   
  138.        
  139.     public Cursor getParentNode(){   
  140.         return db.query("acctitem", new String[]{"_id", "name" }, "pid is null", null, null, null, "pid,_id");         
  141.      
  142.     }   
  143.        
  144.     public Cursor getChildenNode(String pid){   
  145.         Log.v("cola","run getchildenNode");   
  146.         return db.query("acctitem", new String[]{"_id", "name" }, "pid="+pid, null, null, null, "_id");        
  147.     }   
  148.       
  149. }  
  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved