本文考虑把账单界面整理下,实现如下图中的功能。做之前感觉应该不难,但实际做时发现排列界面布局甚至比编写程序代码还要复杂。网上搜索发现,关于这种布局的资料能用的很少,Google Demo中用的最多的就是ListvIEw了,但本实例的界面似乎要复杂一些。
spinner和cursor如何配合使用成了完成此实例过程中的难点,本来应该很简单,但却把我郁闷坏了。
先给大家贴上最终的效果图片:
界面的xml:
XML/HTML代码
<?xml version="1.0" enCoding="utf-8"?> <ScrollVIEw xmlns:androID="http://schemas.androID.com/apk/res/androID" androID:orIEntation="vertical" androID:layout_height="fill_parent" androID:layout_wIDth="fill_parent"> <linearLayout androID:ID="@+ID/linearLayout01" androID:orIEntation="vertical" androID:layout_height="fill_parent" androID:layout_wIDth="fill_parent"> <linearLayout androID:ID="@+ID/linearLayout02" androID:layout_wIDth="wrap_content" androID:layout_height="wrap_content"> <TextVIEw androID:ID="@+ID/TextVIEw01" androID:layout_wIDth="wrap_content" androID:layout_height="wrap_content" androID:text="选择账目" androID:minWIDth="80dip" androID:textAppearance="?androID:attr/textAppearanceLarge"></TextVIEw> <EditText androID:ID="@+ID/edittext_acctitem" androID:layout_wIDth="wrap_content" androID:layout_height="wrap_content" androID:wIDth="200dip" androID:maxlines="1" androID:editable="false" androID:cursorVisible="false"></EditText> </linearLayout> <VIEw androID:layout_wIDth="fill_parent" androID:layout_height="1dip" androID:background="?androID:attr/ListdivIDer"/> <linearLayout androID:ID="@+ID/linearLayout03" androID:layout_wIDth="wrap_content" androID:layout_height="wrap_content"> <TextVIEw androID:ID="@+ID/TextVIEw03" androID:layout_wIDth="wrap_content" androID:layout_height="wrap_content" androID:text="填入费用" androID:minWIDth="80dip" androID:textAppearance="?androID:attr/textAppearanceLarge"></TextVIEw> <EditText androID:ID="@+ID/Fee" androID:layout_wIDth="wrap_content" androID:layout_height="wrap_content" androID:numeric="decimal" androID:wIDth="160dip"></EditText> <TextVIEw androID:ID="@+ID/TextVIEw13" androID:layout_wIDth="wrap_content" androID:layout_height="wrap_content" androID:text="(元)" androID:textAppearance="?androID:attr/textAppearanceLarge"></TextVIEw> </linearLayout> <VIEw androID:layout_wIDth="fill_parent" androID:layout_height="1dip" androID:background="?androID:attr/ListdivIDer"/> <linearLayout androID:ID="@+ID/linearLayout04" androID:layout_height="wrap_content" androID:layout_wIDth="fill_parent"> <TextVIEw androID:ID="@+ID/TextVIEw02" androID:layout_height="wrap_content" androID:text="选择时间" androID:layout_wIDth="fill_parent" androID:fadingEdge="horizontal" androID:height="24dip" androID:drawablepadding="2dip"></TextVIEw> </linearLayout> <linearLayout androID:ID="@+ID/linearLayout05" androID:layout_wIDth="wrap_content" androID:layout_height="wrap_content"> <TextVIEw androID:ID="@+ID/vdate" androID:layout_wIDth="wrap_content" androID:layout_height="wrap_content" androID:textAppearance="?androID:attr/textAppearanceLarge" androID:wIDth="120dip"></TextVIEw> <button androID:ID="@+ID/BtnDate" androID:layout_wIDth="wrap_content" androID:layout_height="wrap_content" androID:text="+" androID:textStyle="bold" androID:textSize="24dip" androID:height="30dip" androID:wIDth="30dip"></button> <TextVIEw androID:ID="@+ID/vtime" androID:layout_wIDth="wrap_content" androID:layout_height="wrap_content" androID:textAppearance="?androID:attr/textAppearanceLarge" androID:wIDth="80dip" androID:gravity="center_horizontal"></TextVIEw> <button androID:ID="@+ID/BtnTime" androID:layout_wIDth="wrap_content" androID:layout_height="wrap_content" androID:text="+" androID:textStyle="bold" androID:textSize="24dip"></button> </linearLayout> <VIEw androID:layout_wIDth="fill_parent" androID:layout_height="1dip" androID:background="?androID:attr/ListdivIDer"/> <linearLayout androID:ID="@+ID/linearLayout06" androID:layout_height="wrap_content" androID:layout_wIDth="fill_parent"> <TextVIEw androID:ID="@+ID/TextVIEw01" androID:layout_wIDth="wrap_content" androID:layout_height="wrap_content" androID:text="账目类型" androID:minWIDth="80dip" androID:textAppearance="?androID:attr/textAppearanceLarge"></TextVIEw> <Spinner androID:ID="@+ID/Spinner01" androID:layout_height="wrap_content" androID:minWIDth="200dip" androID:layout_wIDth="wrap_content"></Spinner> </linearLayout> <VIEw androID:layout_wIDth="fill_parent" androID:layout_height="1dip" androID:background="?androID:attr/ListdivIDer"/> <TextVIEw androID:ID="@+ID/TextVIEw07" androID:layout_height="wrap_content" androID:text="填写备注" androID:layout_wIDth="fill_parent" androID:height="24dip" ></TextVIEw> <EditText androID:ID="@+ID/EditTextDESC" androID:layout_wIDth="fill_parent" androID:layout_height="wrap_content" androID:lines="4" androID:gravity="top"></EditText> <VIEw androID:layout_wIDth="fill_parent" androID:layout_height="1dip" androID:background="?androID:attr/ListdivIDer"/> <linearLayout androID:ID="@+ID/linearLayout08" androID:layout_height="wrap_content" androID:layout_wIDth="fill_parent"> <button androID:ID="@+ID/BtnSave" androID:wIDth="160dip" androID:text="保 存" androID:textStyle="bold" androID:textSize="24dip" androID:layout_wIDth="wrap_content" androID:layout_height="wrap_content"></button> <button androID:ID="@+ID/BtnCancel" androID:wIDth="160dip" androID:text="取 消" androID:textStyle="bold" androID:textSize="24dip" androID:layout_wIDth="wrap_content" androID:layout_height="wrap_content"></button> </linearLayout> <VIEw androID:layout_wIDth="fill_parent" androID:layout_height="1dip" androID:background="?androID:attr/ListdivIDer"/> </linearLayout> </ScrollVIEw>
下面我们来看下spinner和cursor的用法。
主要就是一个SimpleCursorAdapter。
代码如下:
Java代码
s1=(Spinner) findVIEwByID(R.ID.Spinner01); String[] from= new String[]{"caption"};//需要显示游标里面的字段 int[] to=new int[]{androID.R.ID.text1}; Cursor cur=billdb.getUserID(); SimpleCursorAdapter mAdapter=new SimpleCursorAdapter(this,androID.R.layout.simple_spinner_item,cur,from,to); mAdapter.setDropDownVIEwResource(androID.R.layout.simple_spinner_dropdown_item); s1.setAdapter(mAdapter);
我在这儿居然搞了2天,其实写法一直没错,可是每次报未知的行 _ID。这个错误我也知道就是使用SimpleCursorAdapter 该方法的游标里面必须包括一个_ID的字段,可是我的表里面肯定有的,在我重试了无数次后发现,区分大小写,我倒!
而事实上我建表的语句是:
Java代码
db.execsql("Create table tusers (_ID integer primary key autoincrement," + "caption text not null)");
而我在函数getUserID 里面cursor定义是:
Java代码
public Cursor getUserID(){ Log.v("cola","run get users cursor"); return db.query("tusers",new String[]{"_ID","caption" },null,null); }
你单独测试这个cursor是没有问题的。
这都没用问题,也就是在这儿是不区分大小写的。但是如果你用这个cursor 绑定到SimpleCursorAdapter 这个里面去,一定要和建表语句的一致,不然就出错。这儿把我郁闷坏了。
上面界面布局和这个spinner 搞定后,后面就是完善代码,完善界面的功能,没有新的地方了。
在用户选择完账目,填写费用,选择时间,账目类型后就保存进数据库bills表。
附最新的代码Frm_Addbills.java:
Java代码
package com.cola.ui; import java.util.Calendar; import java.util.TimeZone; import androID.app.Activity; import androID.app.AlertDialog; import androID.app.DatePickerDialog; import androID.app.Dialog; import androID.app.TimePickerDialog; import androID.content.DialogInterface; import androID.content.Intent; import androID.database.Cursor; import androID.os.Bundle; import androID.util.Log; import androID.vIEw.KeyEvent; import androID.vIEw.Menu; import androID.vIEw.MenuItem; import androID.vIEw.VIEw; import androID.vIEw.VIEw.OnClickListener; import androID.Widget.button; import androID.Widget.DatePicker; import androID.Widget.EditText; import androID.Widget.SimpleCursorAdapter; import androID.Widget.Spinner; import androID.Widget.TextVIEw; import androID.Widget.TimePicker; import androID.Widget.Toast; public class Frm_Addbills extends Activity implements OnClickListener { EditText edittext_acctitem,EditTextDESC,Fee; TextVIEw mDate; TextVIEw mTime; static final int RG_REQUEST = 0; private int mYear; private int mMonth; private int mDay; private int mHour; private int mMinute; Spinner s1; button BtnDate,BtnTime; button BtnCancel,BtnSave; BilldbHelper billdb; int acctitemID=-1; public voID onCreate(Bundle icicle) { super.onCreate(icicle); setTitle("ColaBox-添加账单"); setContentVIEw(R.layout.frm_addbills); edittext_acctitem = (EditText)findVIEwByID(R.ID.edittext_acctitem); edittext_acctitem.setonClickListener(this); EditTextDESC=(EditText)findVIEwByID(R.ID.EditTextDESC); Fee=(EditText)findVIEwByID(R.ID.Fee); BtnDate=(button)findVIEwByID(R.ID.BtnDate); BtnDate.setonClickListener(this); BtnTime=(button)findVIEwByID(R.ID.BtnTime); BtnTime.setonClickListener(this); BtnCancel=(button)findVIEwByID(R.ID.BtnCancel); BtnCancel.setonClickListener(this); BtnSave=(button)findVIEwByID(R.ID.BtnSave); BtnSave.setonClickListener(this); mDate = (TextVIEw) findVIEwByID(R.ID.vdate); mTime = (TextVIEw) findVIEwByID(R.ID.vtime); //Calendar c=Calendar.getInstance(Locale.CHINA); initTime(); setDatetime(); billdb = new BilldbHelper(this); s1=(Spinner) findVIEwByID(R.ID.Spinner01); String[] from= new String[]{"caption"}; int[] to=new int[]{androID.R.ID.text1}; Cursor cur=billdb.getUserID(); SimpleCursorAdapter mAdapter=new SimpleCursorAdapter(this,to); mAdapter.setDropDownVIEwResource(androID.R.layout.simple_spinner_dropdown_item); s1.setAdapter(mAdapter); } public boolean onCreateOptionsMenu(Menu menu) { super.onCreateOptionsMenu(menu); menu.add(0,1,"账目明细").setIcon(R.drawable.editbills); menu.add(0,2,"账目统计").setIcon(R.drawable.editbills2); menu.add(0,3,"账目报表").setIcon(R.drawable.billsum1); menu.add(0,4,"退 出").setIcon(R.drawable.quit); return true; } public voID onClick(VIEw v) { if (v.equals(edittext_acctitem)) { Log.v("ColaBox","cmd=edittext_acctitem"); Intent intent = new Intent(); intent.setClass(Frm_Addbills.this,Frm_Editacctitem.class); startActivityForResult(intent,RG_REQUEST); } else if (v.equals(BtnTime)){ showDialog(1); } else if (v.equals(BtnDate)){ showDialog(2); } else if (v.equals(BtnCancel)){ cancel(); } else if (v.equals(BtnSave)){ save(); } } public boolean onoptionsItemSelected(MenuItem item) { //Log.v("ColaBox","getmenuitemID=" + item.getItemID()); switch (item.getItemID()) { case 1: return true; case 2: return true; case 3: return true; case 4: QuitApp(); return true; } return false; } public voID QuitApp() { new AlertDialog.Builder(Frm_Addbills.this).setTitle("提示").setMessage( "确定退出?").setIcon(R.drawable.quit).setPositivebutton("确定",new DialogInterface.OnClickListener() { public voID onClick(DialogInterface dialog,int whichbutton) { billdb.close(); finish(); } }).setNegativebutton("取消",int whichbutton) { } }).show(); } protected voID onActivityResult(int requestCode,int resultCode,Intent data) { if (requestCode == RG_REQUEST) { if (resultCode == RESulT_CANCELED) { // setTitle("Canceled..."); } else if (resultCode == RESulT_OK) { // setTitle((String)data.getCharSequenceExtra("DataKey")); edittext_acctitem.setText((String) data.getCharSequenceExtra("name")); acctitemID=Integer.parseInt((String)data.getCharSequenceExtra("ID")); Log.v("cola","get acctitemID="+acctitemID); } } } private voID cancel(){ Log.v("cola","u put cancel btn"); edittext_acctitem.setText(""); Fee.setText(""); acctitemID=-1; initTime();setDatetime(); EditTextDESC.setText(""); } private voID save(){ Log.v("cola","u put save btn"); if (acctitemID==-1){ new AlertDialog.Builder(this) .setMessage("请首先选择账目.") .show(); return; } int fee=0; String s=Fee.getText().toString(); int pos=s.indexOf("."); //Log.v("cola","i="+(s.length()-pos)); if (pos>0){ if (s.length()-pos<3){ s=s+"0"; } fee=Integer.parseInt(s.substring(0,pos)+s.substring(pos+1,pos+3)); }else{ fee=Integer.parseInt(s)*100; } Log.v("cola","u put save btn"); if (billdb.Bills_save(acctitemID,fee,(int)s1.getSelectedItemID(),((TextVIEw)mDate).getText().toString(),((TextVIEw)mTime).getText().toString(),EditTextDESC.getText().toString())){ Toast.makeText(this,"保存成功.",Toast.LENGTH_SHORT).show(); cancel(); }else{ Toast.makeText(this,"保存失败,请检查数据.",Toast.LENGTH_SHORT).show(); } } public boolean onKeyDown(int keyCode,KeyEvent event) { switch (keyCode) { case KeyEvent.KEYCODE_BACK: QuitApp(); return true; } return false; } private voID initTime(){ Calendar c = Calendar. getInstance(TimeZone.getTimeZone("GMT+08:00")); mYear = c.get(Calendar.YEAR); mMonth = c.get(Calendar.MONTH); mDay = c.get(Calendar.DAY_OF_MONTH); mHour = c.get(Calendar.HOUR_OF_DAY); mMinute = c.get(Calendar.MINUTE); } private voID setDatetime(){ mDate.setText(mYear+"-"+mMonth+"-"+mDay); mTime.setText(pad(mHour)+":"+pad(mMinute)); } @OverrIDe protected Dialog onCreateDialog(int ID) { switch (ID) { case 1: return new TimePickerDialog(this,mTimeSetListener,mHour,mMinute,false); case 2: return new DatePickerDialog(this,mDateSetListener,mYear,mMonth,mDay); } return null; } @OverrIDe protected voID onPrepareDialog(int ID,Dialog dialog) { switch (ID) { case 1: ((TimePickerDialog) dialog).updateTime(mHour,mMinute); break; case 2: ((DatePickerDialog) dialog).updateDate(mYear,mDay); break; } } private DatePickerDialog.OnDateSetListener mDateSetListener = new DatePickerDialog.OnDateSetListener() { public voID onDateSet(DatePicker vIEw,int year,int monthOfYear,int dayOfMonth) { mYear = year; mMonth = monthOfYear; mDay = dayOfMonth; setDatetime(); } }; private TimePickerDialog.OnTimeSetListener mTimeSetListener = new TimePickerDialog.OnTimeSetListener() { public voID onTimeSet(TimePicker vIEw,int hourOfDay,int minute) { mHour = hourOfDay; mMinute = minute; setDatetime(); } }; private static String pad(int c) { if (c >= 10) return String.valueOf(c); else return "0" + String.valueOf(c); } }
最新的billdbhelper.java :
Java代码
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,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 autoincrement," +" acctitemID integer," + "fee integer," + "userID integer," + "sdate TEXT," + "stime TEXT," + "desc TEXT" + ");"); Log.v("cola",table exists."); } } public boolean Bills_save(int acctID,int fee,int userID,String date,String time,String text){ String sql=""; try{ sql="insert into bills values(null,"+acctID+","+fee+","+userID+",'"+date+"','"+time+"','"+text+"')"; db.execsql(sql); Log.v("cola","insert table bills ok"); return true; }catch(Exception e){ Log.v("cola","insert table bills err="+sql); return false; } } 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",table exists."); } } public voID Createtable_users() { try{ db.execsql("Create table tusers (_ID integer primary key autoincrement," + "caption text not null)"); Log.v("cola","Create table users ok"); db.execsql("insert into tusers values (null,'个人')"); db.execsql("insert into tusers values (null,'公司')"); }catch(Exception e){ Log.v("cola","Create table tusers err,table exists."); } } public voID Initacctitem() { try{ //s.getBytes(enCoding); db.execsql("insert into acctitem values (1,'收入')"); db.execsql("insert into acctitem values (2,'工资')"); db.execsql("insert into acctitem values (9998,'其他')"); db.execsql("insert into acctitem values (0,'支出')"); db.execsql("insert into acctitem values (3,'生活用品')"); db.execsql("insert into acctitem values (4,'水电煤气费')"); db.execsql("insert into acctitem values (5,'汽油费')"); db.execsql("insert into acctitem values (9999,'其他')"); //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); 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); int n=c.getCount(); if (c.getCount()==0){ Createtable_acctitem(); Createtable_colaconfig(); Createtable_bills(); Createtable_users(); Initacctitem(); } //test(); 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","pID,_ID"); } public Cursor getChildenNode(String pID){ Log.v("cola","run getchildenNode"); return db.query("acctitem","pID="+pID,"_ID"); } public Cursor getUserID(){ Log.v("cola",null); } public String test(){ try{ Cursor c2 =getUserID(); String ss=""; c2.movetoFirst(); while(!c2.isAfterLast()){ ss = c2.getString(0) +","+ c2.getString(1); //byte b[]=c2.getString(1).getBytes(); c2.movetoNext(); Log.v("cola","ss="+ss+""); } return ss; }catch(Exception e){ Log.v("cola","e="+e.getMessage()); return "err"; } } }
系列文章:
Android 个人理财工具六:显示账单明细 下
Android 个人理财工具五:显示账单明细 上
Android 个人理财工具四:添加账单页面 下
Android 个人理财工具三:添加账单页面 上
Android 个人理财工具二:使用SQLite实现启动时初始化数据
Android 个人理财工具一:项目概述与启动界面的实现
以上就AndroID 理财工具详情页面的开发,后续继续补充,其他功能,谢谢大家对本站的支持!
总结以上是内存溢出为你收集整理的Android 个人理财工具四:添加账单页面 下全部内容,希望文章能够帮你解决Android 个人理财工具四:添加账单页面 下所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)