9.SQLite分页表格

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

表格展现数据

这个SQL分页表格控件主要分为“表格区”和“分页栏”这两部分,这两部分都是基于GridView实现的。网上介绍Android上实现表格的DEMO一般都用ListView。ListView与GridView对比,ListView最大的优势是格单元的大小可以自定义,可以某单元长某单元短,但是难于实现自适应数据表的结构;而GridView最大的优势就是自适应数据表的结构,但是格单元统一大小。。。对于数据表结构多变的情况,建议使用GridView实现表格。

本文实现的SQL分页表格控件有以下特点:

1、自适应数据表结构,但是格单元统一大小。
2、支持分页。
3、“表格区”有按键事件回调处理,“分页栏”有分页切换事件回调处理。

本文程序代码较多,可以到这里下载整个工程的源码:testSQLite.rar

items.xml的代码如下,它是“表格区”和“分页栏”的格单元实现:

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

main.xml的代码如下

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
<? xml  version = "1.0"  encoding = "utf-8" ?>
< LinearLayout  xmlns: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" >
     < Button
         android:id = "@+id/btnCreateDB"
         android:layout_height = "wrap_content"
         android:layout_width = "fill_parent"
         android:text = "创建数据库"
         />
     < Button
         android:id = "@+id/btnInsertRec"
         android:layout_height = "wrap_content"
         android:layout_width = "fill_parent"
         android:text = "插入一串实验数据"
         />
     < Button
         android:id = "@+id/btnClose"
         android:layout_width = "fill_parent"
         android:layout_height = "wrap_content"
         android:text = "关闭数据库"
         />
</ LinearLayout >

演示程序testSQLite.java的源码

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

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

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值