ColaBox 登记收支记录终于进入了复杂阶段了.这个界面我也是查找了很多资料以及打开android的源代码看了后才完成了,现在想来Google的开源真是明智的啊.
 gn7pIoN  f'*HP%+Y  从前面的登录页面跳转进入添加账单页面.这个页面主要是用来登记收支记录的.
 R0{+Xd  说白了就是往数据库录入明细.
 n0nkv[  w Xfy,W  表结构就是db.execSQL("CREATE TABLE bills ("
 Onby=Y o6  "_ID INTEGER PRIMARY KEY," //id
 t4 h5R  "fee integer," //费用
 ,NKDEcw]  "acctitemid integer," //账目类型
 h?fv :^vSi  "userid integer," //使用者
 r's4 -\  "sdate TEXT," //日期
 Bglh}_X  "stime TEXT," //时间
 M {_`X  "desc TEXT" //备注
 #W'jNX,h  ");");
 $UgM7V$  Q_qc_IcM y  可以看到主要是录入这些数据.首先是布置界面,我目前想到的用个tablelayout来布局
 !2$O^ }6"  最后布局就是如下图这样
 Z Oyq{w!2  #*1\h=bzmW  图1
 gfFP-J3cN   rW&8#&  gNo.&G [  /t(dhz&xN  b-;+&Rb
 rW&8#&  gNo.&G [  /t(dhz&xN  b-;+&Rb  在这儿我首先需要设置账目,前面我们已经初始化过账目的数据.
 8 U B?X  账目应该是一个ExpandableListActivity 2层的结构.需要从数据库里面读取.我在账目后面放了一个editview 只读没有光标的.也就是在这儿不可录入,在该editview的onclick事件里面我们打开账目选择界面.如下图
 tHJ#2X#Y.  =k 2In_  图2 账目选择
 0' @^PzX  (B}+uI{   k"LbB#Q  ZYos.ay  I;S[Ft8d
 k"LbB#Q  ZYos.ay  I;S[Ft8d  在这个界面中点击子节点就返回前面界面,把选择的账目传递过去.在这有个问题,如果用户需要录入的账目没有怎么办?
 ik=~`3Zp0  所以我这没有用dialog方式而是用了ExpandableListActivity在这个界面中如果长点某个子节点就弹出管理账目菜单,
 \`-/\N  来维护账目,如下图所示:
 OQ;DqV  图3账目选择菜单示意 图4 编辑账目
 ^z-e"  `7zz&f9dDX   ,a9<\bd)  HF" v \
 ,a9<\bd)  HF" v \   C\Qor3];  -9Wx;u4]o  kz\ D-b
 C\Qor3];  -9Wx;u4]o  kz\ D-b  上面这些流程说起来很简单,可是当我用andriod编写时,遇到了很多问题,不过一个个都被我解决了,这正是编程的快乐所在.
 `VCU`Y  关于ExpandableListActivity 大家可以参考android 里面apidemos 里面ExpandableList1,ExpandableList2,ExpandableList3 
=/&ob%J)9]  这里面对熟悉这个ui还是很有帮助的. 在ExpandableList2 里面就是从数据库进行读取的例子. 当然android里面那个我是没太
 ER~m &JI  看明白因为他引用了import android.provider.Contacts.People; 联系人部分的框架,而我目前对数据库的操作和他不一样,我都是直接
 R ,-y  sql访问.
 Y O;N9wu3f  但是你只要搞定2个cursor就ok了. Cursor groupCursor childCursor 其他都由SimpleCursorTreeAdapter帮你实现了.
 .<} (J#vC  下面我们来看看如何使用SimpleCursorTreeAdapter
 t33/QW r  //首先要实现groupcursor就是父节点游标,这个其实就是我的acctitem表的 
?W-J2tgss{  //select * from accitem where pid is null 的结果 
0 {#c  Cursor groupCursor = billdb.getParentNode(); 
>MZWm6M8  // Cache the ID column index 
":E fR`A#  mGroupIdColumnIndex = groupCursor.getColumnIndexOrThrow("_ID"); 
m,NUNd#)\  // Set up our adapter 
0j\?zt?  mAdapter = new MyExpandableListAdapter(groupCursor, this, android.R.layout.simple_expandable_list_item_1, 
(~}IoQp>  android.R.layout.simple_expandable_list_item_1, 
]4wyuP,up  new String[] { "NAME" }, // Name for group layouts 
zBD ?O!  new int[] { android.R.id.text1 },
 8wz%e(  new String[] { "NAME" }, // 
Lsa&A+fru  new int[] { android.R.id.text1 }); 
Nr)v!z~y   setListAdapter(mAdapter); 
spter35b[  rUvjc4O}  //然后我要实现childCursor
 1M+o7HO.mG  //其实就是select * from acctitem where id=pid 的结果 
Wm>[5h%>  public class MyExpandableListAdapter extends SimpleCursorTreeAdapter { 
<y#-I%ed  public MyExpandableListAdapter(Cursor cursor, Context context, 
1xN6V-qk  int groupLayout, int childLayout, String[] groupFrom, 
Pf&\2_H3s9  int[] groupTo, String[] childrenFrom, int[] childrenTo) 
j9"uxw@  { 
A;~lG3j4  super(context, cursor, groupLayout, groupFrom, groupTo, 
c\"t+/Z  childLayout, childrenFrom, childrenTo); 
+vOlA#t%Z  } 
b[&A,ZPh$@  protected Cursor getChildrenCursor(Cursor groupCursor) { 
m(MPVY<X  String pid = groupCursor.getLong(mGroupIdColumnIndex) "";
 $="t7C9S  // Log.v("cola","pid=" pid);
 ~aKM+KmtPH  return billdb.getChildenNode(pid); 
/5cFa  } 
9G njJ  } 
R@*mMWW,  //我们看看Billdbhelper里面的cursor 
_dQVundH  public Cursor getParentNode(){
 QwF\s13  return db.query("acctitem", new String[]{"_id", "name" }, "pid is null", null, null, null, "pid,_id"); 
;. jnRPo";  Md!L@gX6<  }
 ,3 !D(&  xd[GJ;xvs  public Cursor getChildenNode(String pid){
 61qs`N=k  Log.v("cola","run getchildenNode");
 KDx~^OO  return db.query("acctitem", new String[]{"_id", "name" }, "pid=" pid, null, null, null, "_id"); 
+{b!,D3sa*  } 
SVr3OyzI  只要这几步一个2级的tree list就可以出现了. 
>j5,Z]  上面其实才是刚开始,后面我们需要使用一个自定义的Dialog 类似于一个inputBox 因为我们新增账目是需要输入账目的名称.
 \BIa:}9O  就是上面图4表现的.
 e_eNtVq  虽然alertDialog提供了很多方法,可以选择list,treelist,radio, 可惜就是不能录入text.
 aT9+] Ig  这里我参考了api demos 里面的 DateWidgets1.java 和源代码里面DatePickerDialog.java .
 KyQO>g{R  我们可以从alertdialog 继承.然后添加一个Editview 最后把数据返回出来.只要把上面我说的2个java看清楚了后处理起来就简单了.
 [73 \jT  主要是一个回调函数的用法.下面看代码
 B=0U^wL  // 
<F>^ffwGH-  public class Dialog_edit extends AlertDialog implements OnClickListener { 
nRP|Qt7>  private String text = ""; 
*=sMJY9#jE  private EditText edit; 
6Kl%|VrJs  private OnDateSetListener mCallback; //定义回调函数 
cst}/8e  private LinearLayout layout; 
-<g&U*/E  public interface OnDateSetListener {//回调接口 
9.:]eL  void onDateSet(String text); 
3/aK#TjK  } 
>,Z[IAU.x5  protected Dialog_edit(Context context, String title, String value, 
Ipp#{'Do  OnDateSetListener Callback) { 
Qkvg 85  super(context); 
xJ$/#UdP  mCallback = Callback; 
<:n !qQS6  TextView label = new TextView(context); 
{ R`"Nk  label.setText("hint"); 
FI(iqSJ6  // setView(label); 
wHR# -g'  edit = new EditText(context); 
> u!# 4  edit.setText(value); 
0| }]=XN^  layout = new LinearLayout(context); 
Gp9:#L!  layout.setOrientation(LinearLayout.VERTICAL); 
\C}_l+nY  // LinearLayout.LayoutParams param = 
[S_qi,  // new LinearLayout.LayoutParams(100, 40); 
k d9<&.y{  // layout.addView(label, param); 
'* eeup  LinearLayout.LayoutParams param2 = new LinearLayout.LayoutParams(200, 
y,xJ5BI$  50); 
]ft}fU5C1  layout.addView(edit, param2); 
.Y5o&at6s  //添加edit 
!dV2:`|+  setView(layout); 
".7\>8A#a  setTitle(title); 
6qd?&.=r  setButton("确定", this); 
P47 x-;  setButton2("取消", (OnClickListener) null); 
/^sk y!  } 
a7}O.NDf  public void onClick(DialogInterface dialog, int which) { 
uqvS  // Log.v("cola","U click which=" which); 
2&zklXuo:  text = edit.getText().toString(); 
-sxu7I  Log.v("cola", "U click text=" text); 
hr W2#v  if (mCallback != null) 
abw5Gz@Ag  mCallback.onDateSet(text);//使用回调返回录入的数据 
@~bP|a  } 
SQJ +C%   } 
^/I.? :+  这样我们就完成了自定义的dialog 我们可以使用它来新增和编辑账目. 对于账目的增删改就是sql的事情了
 LKBh{X0%(  在这我又遇到一个问题就是我新增一个账目后如何来刷新界面,从而反映账目修改后的变化
 S1#5oy2  在这我开始以为只要使用getExpandableListView().invalidate(); 就可以了,
 =E62N7_`=  因为我之前在ExpandableList1.java例子里面,使用它可以刷新界面.
 tgj 5l#P  在那个例子里面我修改了数组后调用该方法,界面就刷新了,而在这SimpleCursorTreeAdapter就行不通了,我想
 *D67&/g.