Android拔高第九篇之SQLite分页表格

Android提高第九篇之SQLite分页表格

上次讲的Android上的 SQLite分页读取 ,只用文本框显示数据而已,这次就讲得更加深入些,实现并封装一个SQL分页表格控件,不仅支持分页还是以表格的形式展示数据。 先来看看本文程序运行的动画:

Android拔高第九篇之SQLite分页表格

       这个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的代码如下,它是“表格区”和“分页栏”的格单元实现:

view plain copy to clipboard print ?
  1. <? xml   version = "1.0"   encoding = "utf-8" ?>   
  2. < LinearLayout   android:id = "@+id/LinearLayout01"   
  3.     xmlns:android = "http://schemas.android.com/apk/res/android"   
  4.     android:layout_width = "fill_parent"   android:background = "#555555"   
  5.     android:layout_height = "wrap_content" >   
  6.     < TextView   android:layout_below = "@+id/ItemImage"   android:text = "TextView01"   
  7.         android:id = "@+id/ItemText"   android:bufferType = "normal"   
  8.         android:singleLine = "true"   android:background = "#000000"   
  9.         android:layout_width = "fill_parent"   android:gravity = "center"   
  10.         android:layout_margin = "1dip"   android:layout_gravity = "center"   
  11.         android:layout_height = "wrap_content" >   
  12.     </ TextView >   
  13. </ LinearLayout >   

main.xml的代码如下:

view plain copy to clipboard print ?
  1. <? xml   version = "1.0"   encoding = "utf-8" ?>   
  2. < LinearLayout   xmlns:android = "http://schemas.android.com/apk/res/android"   
  3.     android:orientation = "vertical"   android:layout_width = "fill_parent"   
  4.     android:layout_height = "fill_parent"   android:id = "@+id/MainLinearLayout" >   
  5.     < Button   android:layout_height = "wrap_content"   
  6.         android:layout_width = "fill_parent"   android:id = "@+id/btnCreateDB"   
  7.         android:text = "创建数据库" > </ Button >   
  8.     < Button   android:layout_height = "wrap_content"   
  9.         android:layout_width = "fill_parent"   android:text = "插入一串实验数据"   android:id = "@+id/btnInsertRec" > </ Button >   
  10.     < Button   android:layout_height = "wrap_content"   android:id = "@+id/btnClose"   
  11.         android:text = "关闭数据库"   android:layout_width = "fill_parent" > </ Button >   
  12. </ LinearLayout >   

演示程序testSQLite.java的源码:

view plain copy to clipboard print ?
  1. package  com.testSQLite;  
  2. import  android.app.Activity;  
  3. import  android.database.Cursor;  
  4. import  android.database.SQLException;  
  5. import  android.database.sqlite.SQLiteDatabase;  
  6. import  android.os.Bundle;  
  7. import  android.util.Log;  
  8. import  android.view.View;  
  9. import  android.widget.Button;  
  10. import  android.widget.LinearLayout;  
  11. import  android.widget.Toast;  
  12. public   class  testSQLite  extends  Activity {  
  13.     GVTable table;  
  14.     Button btnCreateDB, btnInsert, btnClose;  
  15.     SQLiteDatabase db;  
  16.     int  id; //添加记录时的id累加标记,必须全局   
  17.     private   static   final  String TABLE_NAME =  "stu" ;  
  18.     private   static   final  String ID =  "id" ;  
  19.     private   static   final  String NAME =  "name" ;  
  20.     private   static   final  String PHONE =  "phone" ;  
  21.     private   static   final  String ADDRESS =  "address" ;  
  22.     private   static   final  String AGE =  "age" ;  
  23.       
  24.     @Override   
  25.     public   void  onCreate(Bundle savedInstanceState) {  
  26.         super .onCreate(savedInstanceState);  
  27.         setContentView(R.layout.main);  
  28.         btnCreateDB = (Button) this .findViewById(R.id.btnCreateDB);  
  29.         btnCreateDB.setOnClickListener(new  ClickEvent());  
  30.         btnInsert = (Button) this .findViewById(R.id.btnInsertRec);  
  31.         btnInsert.setOnClickListener(new  ClickEvent());  
  32.         btnClose = (Button) this .findViewById(R.id.btnClose);  
  33.         btnClose.setOnClickListener(new  ClickEvent());  
  34.         table=new  GVTable( this );  
  35.         table.gvSetTableRowCount(8 ); //设置每个分页的ROW总数   
  36.         LinearLayout ly = (LinearLayout) findViewById(R.id.MainLinearLayout);  
  37.         table.setTableOnClickListener(new  GVTable.OnTableClickListener() {  
  38.             @Override   
  39.             public   void  onTableClickListener( int  x, int  y,Cursor c) {  
  40.                 c.moveToPosition(y);  
  41.                 String str=c.getString(x)+" 位置:(" +String.valueOf(x)+ "," +String.valueOf(y)+ ")" ;  
  42.                 Toast.makeText(testSQLite.this , str,  1000 ).show();  
  43.             }  
  44.         });  
  45.         table.setOnPageSwitchListener(new  GVTable.OnPageSwitchListener() {  
  46.               
  47.             @Override   
  48.             public   void  onPageSwitchListener( int  pageID, int  pageCount) {  
  49.                 String str="共有" +String.valueOf(pageCount)+  
  50.                 " 当前第" +String.valueOf(pageID)+ "页" ;  
  51.                 Toast.makeText(testSQLite.this , str,  1000 ).show();  
  52.             }  
  53.         });  
  54.           
  55.         ly.addView(table);  
  56.     }  
  57.     class  ClickEvent  implements  View.OnClickListener {  
  58.         @Override   
  59.         public   void  onClick(View v) {  
  60.             if  (v == btnCreateDB) {  
  61.                 CreateDB();  
  62.             } else   if  (v == btnInsert) {  
  63.                 InsertRecord(16 ); //插入16条记录   
  64.                 table.gvUpdatePageBar("select count(*) from "  + TABLE_NAME,db);  
  65.                 table.gvReadyTable("select * from "  + TABLE_NAME,db);  
  66.             }else   if  (v == btnClose) {  
  67.                 table.gvRemoveAll();  
  68.                 db.close();  
  69.                   
  70.             }  
  71.         }  
  72.     }  
  73.       
  74.     /**  
  75.      * 在内存创建数据库和数据表  
  76.      */   
  77.     void  CreateDB() {  
  78.         // 在内存创建数据库   
  79.         db = SQLiteDatabase.create(null );  
  80.         Log.e("DB Path" , db.getPath());  
  81.         String amount = String.valueOf(databaseList().length);  
  82.         Log.e("DB amount" , amount);  
  83.         // 创建数据表   
  84.         String sql = "CREATE TABLE "  + TABLE_NAME +  " ("  +   
  85.                 ID  + " text not null, "  + NAME +  " text not null,"  +  
  86.                 ADDRESS + " text not null, "  + PHONE +  " text not null,"  +  
  87.                 AGE + " text not null " + ");" ;  
  88.         try  {  
  89.             db.execSQL("DROP TABLE IF EXISTS "  + TABLE_NAME);  
  90.             db.execSQL(sql);  
  91.         } catch  (SQLException e) {}  
  92.     }  
  93.     /**  
  94.      * 插入N条数据  
  95.      */   
  96.     void  InsertRecord( int  n) {  
  97.         int  total = id + n;  
  98.         for  (; id < total; id++) {  
  99.             String sql = "insert into "  + TABLE_NAME +  " ("  +   
  100.             ID + ", "  + NAME+ ", "  + ADDRESS+ ", "  + PHONE+ ", " +AGE  
  101.                     + ") values('"  + String.valueOf(id) +  "', 'man','address','123456789','18');" ;  
  102.             try  {  
  103.                 db.execSQL(sql);  
  104.             } catch  (SQLException e) {  
  105.             }  
  106.         }  
  107.     }  
  108.       
  109.       
  110. }  

分页表格控件GVTable.java的源码:

view plain copy to clipboard print ?
  1. package  com.testSQLite;  
  2. import  java.util.ArrayList;  
  3. import  java.util.HashMap;  
  4. import  android.content.Context;  
  5. import  android.database.Cursor;  
  6. import  android.database.sqlite.SQLiteDatabase;  
  7. import  android.view.View;  
  8. import  android.widget.AdapterView;  
  9. import  android.widget.GridView;  
  10. import  android.widget.LinearLayout;  
  11. import  android.widget.SimpleAdapter;  
  12. import  android.widget.AdapterView.OnItemClickListener;  
  13. public   class  GVTable  extends  LinearLayout {  
  14.     protected  GridView gvTable,gvPage;    
  15.     protected  SimpleAdapter saPageID,saTable; // 适配器   
  16.     protected  ArrayList<HashMap<String, String>> srcPageID,srcTable; // 数据源   
  17.       
  18.     protected   int  TableRowCount= 10 ; //分页时,每页的Row总数   
  19.     protected   int  TableColCount= 0 ; //每页col的数量   
  20.     protected  SQLiteDatabase db;  
  21.     protected  String rawSQL= "" ;  
  22.     protected  Cursor curTable; //分页时使用的Cursor   
  23.     protected  OnTableClickListener clickListener; //整个分页控件被点击时的回调函数   
  24.     protected  OnPageSwitchListener switchListener; //分页切换时的回调函数   
  25.       
  26.     public  GVTable(Context context) {  
  27.         super (context);  
  28.         this .setOrientation(VERTICAL); //垂直   
  29.         //----------------------------------------   
  30.         gvTable=new  GridView(context);  
  31.         addView(gvTable, new  LinearLayout.LayoutParams(LayoutParams.FILL_PARENT,  
  32.                 LayoutParams.WRAP_CONTENT));//宽长式样   
  33.           
  34.         srcTable = new  ArrayList<HashMap<String, String>>();  
  35.         saTable = new  SimpleAdapter(context,  
  36.                 srcTable,// 数据来源   
  37.                 R.layout.items,//XML实现   
  38.                 new  String[] {  "ItemText"  }, // 动态数组与ImageItem对应的子项   
  39.                 new   int [] { R.id.ItemText });  
  40.         // 添加并且显示   
  41.         gvTable.setAdapter(saTable);  
  42.         gvTable.setOnItemClickListener(new  OnItemClickListener(){  
  43.             @Override   
  44.             public   void  onItemClick(AdapterView<?> arg0, View arg1,  int  arg2,  
  45.                     long  arg3) {  
  46.                 int  y=arg2/curTable.getColumnCount()- 1 ; //标题栏的不算   
  47.                 int  x=arg2 % curTable.getColumnCount();  
  48.                 if  (clickListener !=  null //分页数据被点击   
  49.                         && y!=-1 ) { //点中的不是标题栏时   
  50.                     clickListener.onTableClickListener(x,y,curTable);  
  51.                 }  
  52.             }  
  53.         });  
  54.           
  55.         //----------------------------------------   
  56.         gvPage=new  GridView(context);  
  57.         gvPage.setColumnWidth(40 ); //设置每个分页按钮的宽度   
  58.         gvPage.setNumColumns(GridView.AUTO_FIT);//分页按钮数量自动设置   
  59.         addView(gvPage, new  LinearLayout.LayoutParams(LayoutParams.FILL_PARENT,  
  60.                 LayoutParams.WRAP_CONTENT));//宽长式样   
  61.         srcPageID = new  ArrayList<HashMap<String, String>>();  
  62.         saPageID = new  SimpleAdapter(context,  
  63.                 srcPageID,// 数据来源   
  64.                 R.layout.items,//XML实现   
  65.                 new  String[] {  "ItemText"  }, // 动态数组与ImageItem对应的子项   
  66.                 new   int [] { R.id.ItemText });  
  67.         // 添加并且显示   
  68.         gvPage.setAdapter(saPageID);  
  69.         // 添加消息处理   
  70.         gvPage.setOnItemClickListener(new  OnItemClickListener(){  
  71.             @Override   
  72.             public   void  onItemClick(AdapterView<?> arg0, View arg1,  int  arg2,  
  73.                     long  arg3) {  
  74.                 LoadTable(arg2);//根据所选分页读取对应的数据   
  75.                 if (switchListener!= null ){ //分页切换时   
  76.                     switchListener.onPageSwitchListener(arg2,srcPageID.size());  
  77.                 }  
  78.             }  
  79.         });  
  80.     }  
  81.     /**  
  82.      * 清除所有数据  
  83.      */   
  84.     public   void  gvRemoveAll()  
  85.     {  
  86.         if ( this .curTable!= null )  
  87.             curTable.close();  
  88.         srcTable.clear();  
  89.         saTable.notifyDataSetChanged();  
  90.       
  91.         srcPageID.clear();  
  92.         saPageID.notifyDataSetChanged();  
  93.           
  94.     }  
  95.     /**  
  96.      * 读取指定ID的分页数据,返回当前页的总数据  
  97.      * SQL:Select * From TABLE_NAME Limit 9 Offset 10;  
  98.      * 表示从TABLE_NAME表获取数据,跳过10行,取9行  
  99.      * @param pageID 指定的分页ID  
  100.      */   
  101.     protected   void  LoadTable( int  pageID)  
  102.     {  
  103.         if (curTable!= null ) //释放上次的数据   
  104.             curTable.close();  
  105.           
  106.         String sql= rawSQL+" Limit " +String.valueOf(TableRowCount)+  " Offset "  +String.valueOf(pageID*TableRowCount);  
  107.         curTable = db.rawQuery(sql, null );  
  108.           
  109.         gvTable.setNumColumns(curTable.getColumnCount());//表现为表格的关键点!   
  110.         TableColCount=curTable.getColumnCount();  
  111.         srcTable.clear();  
  112.         // 取得字段名称   
  113.         int  colCount = curTable.getColumnCount();  
  114.         for  ( int  i =  0 ; i < colCount; i++) {  
  115.             HashMap<String, String> map = new  HashMap<String, String>();  
  116.             map.put("ItemText" , curTable.getColumnName(i));  
  117.             srcTable.add(map);  
  118.         }  
  119.           
  120.         // 列举出所有数据   
  121.         int  recCount=curTable.getCount();  
  122.         for  ( int  i =  0 ; i < recCount; i++) { //定位到一条数据   
  123.             curTable.moveToPosition(i);  
  124.             for ( int  ii= 0 ;ii<colCount;ii++) //定位到一条数据中的每个字段   
  125.             {  
  126.                 HashMap<String, String> map = new  HashMap<String, String>();  
  127.                 map.put("ItemText" , curTable.getString(ii));  
  128.                 srcTable.add(map);  
  129.             }  
  130.         }  
  131.           
  132.         saTable.notifyDataSetChanged();  
  133.     }  
  134.     /**  
  135.      * 设置表格的最多显示的行数  
  136.      * @param row 表格的行数  
  137.      */   
  138.     public   void  gvSetTableRowCount( int  row)  
  139.     {  
  140.         TableRowCount=row;  
  141.     }  
  142.       
  143.     /**  
  144.      * 取得表格的最大行数      
  145.      * @return 行数  
  146.      */   
  147.     public   int  gvGetTableRowCount()  
  148.     {  
  149.         return  TableRowCount;  
  150.     }  
  151.       
  152.     /**  
  153.      * 取得当前分页的Cursor  
  154.      * @return 当前分页的Cursor  
  155.      */   
  156.     public  Cursor gvGetCurrentTable()  
  157.     {  
  158.         return  curTable;  
  159.     }  
  160.           
  161.     /**  
  162.      * 准备分页显示数据  
  163.      * @param rawSQL sql语句  
  164.      * @param db 数据库  
  165.      */   
  166.     public   void  gvReadyTable(String rawSQL,SQLiteDatabase db)  
  167.     {  
  168.         this .rawSQL=rawSQL;  
  169.         this .db=db;  
  170.     }  
  171.       
  172.     /**  
  173.      * 刷新分页栏,更新按钮数量  
  174.      * @param sql SQL语句  
  175.      * @param db 数据库  
  176.      */   
  177.     public   void  gvUpdatePageBar(String sql,SQLiteDatabase db)  
  178.     {  
  179.         Cursor rec = db.rawQuery(sql, null );  
  180.         rec.moveToLast();  
  181.         long  recSize=rec.getLong( 0 ); //取得总数   
  182.         rec.close();  
  183.         int  pageNum=( int )(recSize/TableRowCount) +  1 ; //取得分页数   
  184.           
  185.         srcPageID.clear();  
  186.         for  ( int  i =  0 ; i < pageNum; i++) {  
  187.             HashMap<String, String> map = new  HashMap<String, String>();  
  188.             map.put("ItemText" "No."  + String.valueOf(i)); // 添加图像资源的ID   
  189.             srcPageID.add(map);  
  190.         }  
  191.         saPageID.notifyDataSetChanged();  
  192.     }  
  193.     //---------------------   
  194.     /**  
  195.      * 表格被点击时的回调函数  
  196.      */   
  197.     public   void  setTableOnClickListener(OnTableClickListener click) {  
  198.         this .clickListener = click;  
  199.     }  
  200.       
  201.     public   interface  OnTableClickListener {  
  202.         public   void  onTableClickListener( int  x, int  y,Cursor c);  
  203.     }  
  204.     //---------------------   
  205.     /**  
  206.      * 分页栏被点击时的回调函数  
  207.      */   
  208.     public   void  setOnPageSwitchListener(OnPageSwitchListener pageSwitch) {  
  209.         this .switchListener = pageSwitch;  
  210.     }  
  211.     public   interface  OnPageSwitchListener {  
  212.         public   void  onPageSwitchListener( int  pageID, int  pageCount);  
  213.     }  
  214. }