本文考虑把账单界面整理下,实现如下图中的功能。做之前感觉应该不难,但实际做时发现排列界面布局甚至比编写程序代码还要复杂。网上搜索发现,关于这种布局的资料能用的很少,Google Demo中用的最多的就是Listview了,但本实例的界面似乎要复杂一些。
spinner和cursor如何配合使用成了完成此实例过程中的难点,本来应该很简单,但却把我郁闷坏了。
先给大家贴上最终的效果图片:
界面的xml:
- <?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。
代码如下:
- 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的字段,可是我的表里面肯定有的,在我重试了无数次后发现,区分大小写,我倒!
而事实上我建表的语句是:
- db.execSQL("Create table tusers (_id integer primary key autoincrement," +
- "caption text not null)");
而我在函数getUserid 里面cursor定义是:
- public Cursor getUserid(){
- Log.v("cola","run get users cursor");
- return db.query("tusers", new String[]{"_ID", "caption" }, null, null, null, null, null);
- }
你单独测试这个cursor是没有问题的。
这都没用问题,也就是在这儿是不区分大小写的。但是如果你用这个cursor 绑定到SimpleCursorAdapter 这个里面去,一定要和建表语句的一致,不然就出错。这儿把我郁闷坏了。
上面界面布局和这个spinner 搞定后,后面就是完善代码,完善界面的功能,没有新的地方了。
在用户选择完账目,填写费用,选择时间,账目类型后就保存进数据库bills表。
附最新的代码Frm_Addbills.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,android.R.layout.simple_spinner_item, cur,from, 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, 0, "账目明细").setIcon(R.drawable.editbills);
- menu.add(0, 2, 0, "账目统计").setIcon(R.drawable.editbills2);
- menu.add(0, 3, 0, "账目报表").setIcon(R.drawable.billsum1);
- menu.add(0, 4, 0, "退 出").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("取消",
- new DialogInterface.OnClickListener() {
- public void onClick(DialogInterface dialog, 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, mMonth, 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 :
- 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 autoincrement,"
- +" 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 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","Create Table acctitem err,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,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();
- 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", 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");
- }
- public Cursor getUserid(){
- Log.v("cola","run get users cursor");
- return db.query("tusers", new String[]{"_id", "caption" }, null, null, null, null, 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";
- }
- }
- }
发表评论:
◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。