Android提高第九篇之SQLite分页表格
本文来自http://blog.****.net/hellogv/,引用必须注明出处!
上次讲的Android上的SQLite分页读取,只用文本框显示数据而已,这次就讲得更加深入些,实现并封装一个SQL分页表格控件,不仅支持分页还是以表格的形式展示数据。先来看看本文程序运行的动画:
这个SQL分页表格控件主要分为“表格区”和“分页栏”这两部分,这两部分都是基于GridView实现的。网上介绍Android上实现表格的DEMO一般都用ListView。ListView与GridView对比,ListView最大的优势是格单元的大小可以自定义,可以某单元长某单元短,但是难于实现自适应数据表的结构;而GridView最大的优势就是自适应数据表的结构,但是格单元统一大小。。。对于数据表结构多变的情况,建议使用GridView实现表格。
本文实现的SQL分页表格控件有以下特点:
1.自适应数据表结构,但是格单元统一大小;
2.支持分页;
3.“表格区”有按键事件回调处理,“分页栏”有分页切换事件回调处理。
本文程序代码较多,可以到这里下载整个工程的源码:http://www.rayfile.com/files/72e78b68-f2e5-11df-8469-0015c55db73d/
items.xml的代码如下,它是“表格区”和“分页栏”的格单元实现:
- <?xmlversion="1.0"encoding="utf-8"?>
- <LinearLayoutandroid:id="@+id/LinearLayout01"
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="fill_parent"android:background="#555555"
- android:layout_height="wrap_content">
- <TextViewandroid:layout_below="@+id/ItemImage"android:text="TextView01"
- android:id="@+id/ItemText"android:bufferType="normal"
- android:singleLine="true"android:background="#000000"
- android:layout_width="fill_parent"android:gravity="center"
- android:layout_margin="1dip"android:layout_gravity="center"
- android:layout_height="wrap_content">
- </TextView>
- </LinearLayout>
main.xml的代码如下:
- <?xmlversion="1.0"encoding="utf-8"?>
- <LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android"
- android:orientation="vertical"android:layout_width="fill_parent"
- android:layout_height="fill_parent"android:id="@+id/MainLinearLayout">
- <Buttonandroid:layout_height="wrap_content"
- android:layout_width="fill_parent"android:id="@+id/btnCreateDB"
- android:text="创建数据库"></Button>
- <Buttonandroid:layout_height="wrap_content"
- android:layout_width="fill_parent"android:text="插入一串实验数据"android:id="@+id/btnInsertRec"></Button>
- <Buttonandroid:layout_height="wrap_content"android:id="@+id/btnClose"
- android:text="关闭数据库"android:layout_width="fill_parent"></Button>
- </LinearLayout>
演示程序testSQLite.java的源码:
- packagecom.testSQLite;
- importandroid.app.Activity;
- importandroid.database.Cursor;
- importandroid.database.SQLException;
- importandroid.database.sqlite.SQLiteDatabase;
- importandroid.os.Bundle;
- importandroid.util.Log;
- importandroid.view.View;
- importandroid.widget.Button;
- importandroid.widget.LinearLayout;
- importandroid.widget.Toast;
- publicclasstestSQLiteextendsActivity{
- GVTabletable;
- ButtonbtnCreateDB,btnInsert,btnClose;
- SQLiteDatabasedb;
- intid;//添加记录时的id累加标记,必须全局
- privatestaticfinalStringTABLE_NAME="stu";
- privatestaticfinalStringID="id";
- privatestaticfinalStringNAME="name";
- privatestaticfinalStringPHONE="phone";
- privatestaticfinalStringADDRESS="address";
- privatestaticfinalStringAGE="age";
- @Override
- publicvoidonCreate(BundlesavedInstanceState){
- super.onCreate(savedInstanceState);
- setContentView(R.layout.main);
- btnCreateDB=(Button)this.findViewById(R.id.btnCreateDB);
- btnCreateDB.setOnClickListener(newClickEvent());
- btnInsert=(Button)this.findViewById(R.id.btnInsertRec);
- btnInsert.setOnClickListener(newClickEvent());
- btnClose=(Button)this.findViewById(R.id.btnClose);
- btnClose.setOnClickListener(newClickEvent());
- table=newGVTable(this);
- table.gvSetTableRowCount(8);//设置每个分页的ROW总数
- LinearLayoutly=(LinearLayout)findViewById(R.id.MainLinearLayout);
- table.setTableOnClickListener(newGVTable.OnTableClickListener(){
- @Override
- publicvoidonTableClickListener(intx,inty,Cursorc){
- c.moveToPosition(y);
- Stringstr=c.getString(x)+"位置:("+String.valueOf(x)+","+String.valueOf(y)+")";
- Toast.makeText(testSQLite.this,str,1000).show();
- }
- });
- table.setOnPageSwitchListener(newGVTable.OnPageSwitchListener(){
- @Override
- publicvoidonPageSwitchListener(intpageID,intpageCount){
- Stringstr="共有"+String.valueOf(pageCount)+
- "当前第"+String.valueOf(pageID)+"页";
- Toast.makeText(testSQLite.this,str,1000).show();
- }
- });
- ly.addView(table);
- }
- classClickEventimplementsView.OnClickListener{
- @Override
- publicvoidonClick(Viewv){
- if(v==btnCreateDB){
- CreateDB();
- }elseif(v==btnInsert){
- InsertRecord(16);//插入16条记录
- table.gvUpdatePageBar("selectcount(*)from"+TABLE_NAME,db);
- table.gvReadyTable("select*from"+TABLE_NAME,db);
- }elseif(v==btnClose){
- table.gvRemoveAll();
- db.close();
- }
- }
- }
- /**
- *在内存创建数据库和数据表
- */
- voidCreateDB(){
- //在内存创建数据库
- db=SQLiteDatabase.create(null);
- Log.e("DBPath",db.getPath());
- Stringamount=String.valueOf(databaseList().length);
- Log.e("DBamount",amount);
- //创建数据表
- Stringsql="CREATETABLE"+TABLE_NAME+"("+
- ID+"textnotnull,"+NAME+"textnotnull,"+
- ADDRESS+"textnotnull,"+PHONE+"textnotnull,"+
- AGE+"textnotnull"+");";
- try{
- db.execSQL("DROPTABLEIFEXISTS"+TABLE_NAME);
- db.execSQL(sql);
- }catch(SQLExceptione){}
- }
- /**
- *插入N条数据
- */
- voidInsertRecord(intn){
- inttotal=id+n;
- for(;id<total;id++){
- Stringsql="insertinto"+TABLE_NAME+"("+
- ID+","+NAME+","+ADDRESS+","+PHONE+","+AGE
- +")values('"+String.valueOf(id)+"','man','address','123456789','18');";
- try{
- db.execSQL(sql);
- }catch(SQLExceptione){
- }
- }
- }
- }
分页表格控件GVTable.java的源码:
- packagecom.testSQLite;
- importjava.util.ArrayList;
- importjava.util.HashMap;
- importandroid.content.Context;
- importandroid.database.Cursor;
- importandroid.database.sqlite.SQLiteDatabase;
- importandroid.view.View;
- importandroid.widget.AdapterView;
- importandroid.widget.GridView;
- importandroid.widget.LinearLayout;
- importandroid.widget.SimpleAdapter;
- importandroid.widget.AdapterView.OnItemClickListener;
- publicclassGVTableextendsLinearLayout{
- protectedGridViewgvTable,gvPage;
- protectedSimpleAdaptersaPageID,saTable;//适配器
- protectedArrayList<HashMap<String,String>>srcPageID,srcTable;//数据源
- protectedintTableRowCount=10;//分页时,每页的Row总数
- protectedintTableColCount=0;//每页col的数量
- protectedSQLiteDatabasedb;
- protectedStringrawSQL="";
- protectedCursorcurTable;//分页时使用的Cursor
- protectedOnTableClickListenerclickListener;//整个分页控件被点击时的回调函数
- protectedOnPageSwitchListenerswitchListener;//分页切换时的回调函数
- publicGVTable(Contextcontext){
- super(context);
- this.setOrientation(VERTICAL);//垂直
- //----------------------------------------
- gvTable=newGridView(context);
- addView(gvTable,newLinearLayout.LayoutParams(LayoutParams.FILL_PARENT,
- LayoutParams.WRAP_CONTENT));//宽长式样
- srcTable=newArrayList<HashMap<String,String>>();
- saTable=newSimpleAdapter(context,
- srcTable,//数据来源
- R.layout.items,//XML实现
- newString[]{"ItemText"},//动态数组与ImageItem对应的子项
- newint[]{R.id.ItemText});
- //添加并且显示
- gvTable.setAdapter(saTable);
- gvTable.setOnItemClickListener(newOnItemClickListener(){
- @Override
- publicvoidonItemClick(AdapterView<?>arg0,Viewarg1,intarg2,
- longarg3){
- inty=arg2/curTable.getColumnCount()-1;//标题栏的不算
- intx=arg2%curTable.getColumnCount();
- if(clickListener!=null//分页数据被点击
- &&y!=-1){//点中的不是标题栏时
- clickListener.onTableClickListener(x,y,curTable);
- }
- }
- });
- //----------------------------------------
- gvPage=newGridView(context);
- gvPage.setColumnWidth(40);//设置每个分页按钮的宽度
- gvPage.setNumColumns(GridView.AUTO_FIT);//分页按钮数量自动设置
- addView(gvPage,newLinearLayout.LayoutParams(LayoutParams.FILL_PARENT,
- LayoutParams.WRAP_CONTENT));//宽长式样
- srcPageID=newArrayList<HashMap<String,String>>();
- saPageID=newSimpleAdapter(context,
- srcPageID,//数据来源
- R.layout.items,//XML实现
- newString[]{"ItemText"},//动态数组与ImageItem对应的子项
- newint[]{R.id.ItemText});
- //添加并且显示
- gvPage.setAdapter(saPageID);
- //添加消息处理
- gvPage.setOnItemClickListener(newOnItemClickListener(){
- @Override
- publicvoidonItemClick(AdapterView<?>arg0,Viewarg1,intarg2,
- longarg3){
- LoadTable(arg2);//根据所选分页读取对应的数据
- if(switchListener!=null){//分页切换时
- switchListener.onPageSwitchListener(arg2,srcPageID.size());
- }
- }
- });
- }
- /**
- *清除所有数据
- */
- publicvoidgvRemoveAll()
- {
- if(this.curTable!=null)
- curTable.close();
- srcTable.clear();
- saTable.notifyDataSetChanged();
- srcPageID.clear();
- saPageID.notifyDataSetChanged();
- }
- /**
- *读取指定ID的分页数据,返回当前页的总数据
- *SQL:Select*FromTABLE_NAMELimit9Offset10;
- *表示从TABLE_NAME表获取数据,跳过10行,取9行
- *@parampageID指定的分页ID
- */
- protectedvoidLoadTable(intpageID)
- {
- if(curTable!=null)//释放上次的数据
- curTable.close();
- Stringsql=rawSQL+"Limit"+String.valueOf(TableRowCount)+"Offset"+String.valueOf(pageID*TableRowCount);
- curTable=db.rawQuery(sql,null);
- gvTable.setNumColumns(curTable.getColumnCount());//表现为表格的关键点!
- TableColCount=curTable.getColumnCount();
- srcTable.clear();
- //取得字段名称
- intcolCount=curTable.getColumnCount();
- for(inti=0;i<colCount;i++){
- HashMap<String,String>map=newHashMap<String,String>();
- map.put("ItemText",curTable.getColumnName(i));
- srcTable.add(map);
- }
- //列举出所有数据
- intrecCount=curTable.getCount();
- for(inti=0;i<recCount;i++){//定位到一条数据
- curTable.moveToPosition(i);
- for(intii=0;ii<colCount;ii++)//定位到一条数据中的每个字段
- {
- HashMap<String,String>map=newHashMap<String,String>();
- map.put("ItemText",curTable.getString(ii));
- srcTable.add(map);
- }
- }
- saTable.notifyDataSetChanged();
- }
- /**
- *设置表格的最多显示的行数
- *@paramrow表格的行数
- */
- publicvoidgvSetTableRowCount(introw)
- {
- TableRowCount=row;
- }
- /**
- *取得表格的最大行数
- *@return行数
- */
- publicintgvGetTableRowCount()
- {
- returnTableRowCount;
- }
- /**
- *取得当前分页的Cursor
- *@return当前分页的Cursor
- */
- publicCursorgvGetCurrentTable()
- {
- returncurTable;
- }
- /**
- *准备分页显示数据
- *@paramrawSQLsql语句
- *@paramdb数据库
- */
- publicvoidgvReadyTable(StringrawSQL,SQLiteDatabasedb)
- {
- this.rawSQL=rawSQL;
- this.db=db;
- }
- /**
- *刷新分页栏,更新按钮数量
- *@paramsqlSQL语句
- *@paramdb数据库
- */
- publicvoidgvUpdatePageBar(Stringsql,SQLiteDatabasedb)
- {
- Cursorrec=db.rawQuery(sql,null);
- rec.moveToLast();
- longrecSize=rec.getLong(0);//取得总数
- rec.close();
- intpageNum=(int)(recSize/TableRowCount)+1;//取得分页数
- srcPageID.clear();
- for(inti=0;i<pageNum;i++){
- HashMap<String,String>map=newHashMap<String,String>();
- map.put("ItemText","No."+String.valueOf(i));//添加图像资源的ID
- srcPageID.add(map);
- }
- saPageID.notifyDataSetChanged();
- }
- //---------------------------------------------------------
- /**
- *表格被点击时的回调函数
- */
- publicvoidsetTableOnClickListener(OnTableClickListenerclick){
- this.clickListener=click;
- }
- publicinterfaceOnTableClickListener{
- publicvoidonTableClickListener(intx,inty,Cursorc);
- }
- //---------------------------------------------------------
- /**
- *分页栏被点击时的回调函数
- */
- publicvoidsetOnPageSwitchListener(OnPageSwitchListenerpageSwitch){
- this.switchListener=pageSwitch;
- }
- publicinterfaceOnPageSwitchListener{
- publicvoidonPageSwitchListener(intpageID,intpageCount);
- }
- }