Android之自制的分页表格控件
网页上经常有分页表格的出现,同样的在Android上也可以实现。Android本身并没有直接提供表格这个控件,一般可以用GridView来实现比较简单,但是每个数据显示的长宽会一样。当然,也可以用ListView来实现,这个灵活定义每个数据显示的长宽。还有一种,是采用布局TableLayout来实现等等。这里用GridView,来实现一个。
它有几个特点:
1、实现分页;
2、简便的翻页按钮设置;
3、点击顶部字段名称会改变排序方式;
4、使用方便,只需几个参数。
(一)截图:
(二)关键部分:
1、视图架构:
该分页视图控件,由三部分组成:顶部:字段视图:gv_titles,主体:数据视图:gv_body,底部:分页按钮视图:bottomlayout。
2、SQl分页查询语句:
//查询语句
sql += " Limit " + TableRowCount + " Offset " + stratIndex;
3、排序方式的改变
String sql = "select * from (" + SimpleTable.this.sql +
" Limit " + TableRowCount + " Offset " + pageID * TableRowCount + ") tempTable order by " +
items[arg2][0] ;
if(isDesc[arg2]) {
sql += " asc ";
isDesc[arg2] = false;
}else {
sql += " desc ";
isDesc[arg2] = true;
}
Log.e("sql", sql);
toPage(0, sql);
}
});
(三)代码:
1、数据项布局文件:items.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout android: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">
<TextView android: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>
2、Activity类:PaginatingTable
package com.myandroid.test;
import java.util.HashMap;
import java.util.Map;
import android.app.Activity;
import android.os.Bundle;
import android.view.ViewGroup;
import android.view.ViewGroup.LayoutParams;
import android.widget.LinearLayout;
public class PaginatingTable extends Activity {
private LinearLayout linearLayout;
private SimpleTable simpleTable;
private String[][] items;
private String sql;
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
linearLayout = (LinearLayout)findViewById(R.id.linearLayout);
//要查询的字段和对应显示的名称
items = new String[][]{
{"id", "序列"},
{"name", "姓名"},
{"time", "登陆时间"},
};
//插入一些数据测试用
SQLiteUtility.insertSomething(this);
//查询语句
String sql = "select * from myTable";
//创建分页表格视图,只需要传入几个参数
SimpleTable simpleTable = new SimpleTable(this, items, sql, 7);
linearLayout.addView(simpleTable);
// addContentView(simpleTable, new ViewGroup.LayoutParams(ViewGroup.LayoutParams.FILL_PARENT,
// ViewGroup.LayoutParams.WRAP_CONTENT));
}
}
3、分页表格类:SimpleTable
package com.myandroid.test;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import android.content.Context;
import android.database.Cursor;
import android.graphics.Color;
import android.graphics.Shader.TileMode;
import android.graphics.Typeface;
import android.util.Log;
import android.view.Gravity;
import android.view.View;
import android.view.ViewGroup.LayoutParams;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.AdapterView.OnItemSelectedListener;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.GridView;
import android.widget.LinearLayout;
import android.widget.SimpleAdapter;
import android.widget.Spinner;
import android.widget.TextView;
import android.widget.Toast;
import android.view.View.OnClickListener;
public class SimpleTable extends LinearLayout implements OnClickListener, OnItemSelectedListener,
OnItemClickListener{
private Context context; //上下文
private GridView gv_titles; //字段视图
private GridView gv_body; //数据视图
private LinearLayout bottomLayout; //视图底部布局
private Button bt_next, bt_pre, bt_first, bt_last; //按钮:下一页、上一页、首页、尾页
private TextView tv_page, tv_count;
private Spinner sp_page; //页码下拉框
private String[][] items; //[字段][显示的名称]
private String sql; //查询语句
private SimpleAdapter titlesAdatper; //字段视图适配器
private SimpleAdapter datasAdatper; //数据视图适配去
private int TableRowCount; //每页显示条数
private int pageID; //当前页码
private int TotalCount; //总记录条数
private int pageCount; //总页数
private String TableName; //表名和查询条件
private String[] fields; //字段名称
private boolean[] isDesc; //排序方式标记:false-递增排序,true-递减排序
private ArrayList<HashMap<String, String>> dataList; //数据集合
public SimpleTable(Context context) {
super(context);
this.context = context;
}
/**
* 表格视图
* @param context 上下文
* @param items 字段名和对应显示名称
* @param sql SQl查询语句
* @param displayNum 每页的最大记录数
*/
public SimpleTable(Context context, String[][] items, String sql, int TableRowCount) {
super(context);
this.context = context;
this.items = items;
this.sql = sql.replace(";", "");
this.TableRowCount = TableRowCount;
//排序方式标记:false-递增排序,true-递减排序
isDesc = new boolean[items.length];
//当前页码
pageID = 0;
//表名称和查询条件
TableName = sql.toLowerCase().substring(sql.toLowerCase().indexOf(" from ")+5, sql.length()).trim();
//记录总数
TotalCount = SQLiteUtility.getCount(context, "select count(*) from " + TableName);
//总页码
pageCount = TotalCount%TableRowCount==0? TotalCount/TableRowCount-1 : TotalCount/TableRowCount;
//字段名称
fields = new String[items.length];
for (int i = 0; i < items.length; i++) {
fields[i] = items[i][0];
}
setField(); //字段视图
setBody(); //数据视图
setBottomLayout(); //底部视图
setOrientation(LinearLayout.VERTICAL);
addView(gv_titles); //添加视图
addView(gv_body);
addView(bottomLayout);
}
/**
* 设置字段视图
*/
private void setField() {
gv_titles = new GridView(context);
gv_titles.setNumColumns(items.length);
//字段标题
ArrayList<HashMap<String, String>> titles = new ArrayList<HashMap<String, String>>();
for(int i = 0; i < items.length; i++) {
HashMap<String, String> map = new HashMap<String, String>();
map.put("title", items[i][1]);
titles.add(map);
}
titlesAdatper = new SimpleAdapter(context, titles,
R.layout.items, new String[]{"title"}, new int[] {R.id.ItemText});
gv_titles.setAdapter(titlesAdatper);
//点击字段标题,改变排序方式
gv_titles.setOnItemClickListener(new OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> arg0, View arg1, int arg2,
long arg3) {
String sql = "select * from (" + SimpleTable.this.sql +
" Limit " + TableRowCount + " Offset " + pageID * TableRowCount + ") tempTable order by " +
items[arg2][0] ;
if(isDesc[arg2]) {
sql += " asc ";
isDesc[arg2] = false;
}else {
sql += " desc ";
isDesc[arg2] = true;
}
Log.e("sql", sql);
toPage(0, sql);
}
});
}
/**
* 设置表格数据视图
*/
private void setBody() {
gv_body = new GridView(context);
gv_body.setNumColumns(items.length);
toPage(0, this.sql); //转到第一页
gv_body.setOnItemClickListener(this); //点击数据事件
}
/**
* 设置底部翻页视图,
* 由如下组成:首页、上一页、下一页、尾页、页码选择、当期页码提示
*/
private void setBottomLayout() {
//底部容器
bottomLayout = new LinearLayout(context);
bottomLayout.setOrientation(LinearLayout.HORIZONTAL);
bottomLayout.setLayoutParams(new LayoutParams(
LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT));
//翻页按钮
bt_pre = new Button(context); //上一页
bt_next = new Button(context); //下一页
bt_first = new Button(context); //首页
bt_last = new Button(context); //尾页
sp_page = new Spinner(context); //页码
tv_page = new TextView(context);//页码
//设置文本
bt_pre.setText("上一页");
bt_next.setText("下一页");
bt_first.setText("首页");
bt_last.setText("尾页");
tv_page.setText("页码:");
//设置页码下拉框选项
List<Integer> list = new ArrayList<Integer>();
for(int i = 0; i <= pageCount; i++) {
list.add(i);
}
ArrayAdapter<Integer> pageAdapter = new ArrayAdapter<Integer>(context, android.R.layout.simple_spinner_item, list);
sp_page.setAdapter(pageAdapter);
//设置事件
sp_page.setOnItemSelectedListener(this); //设置下拉框事件
bt_first.setOnClickListener(this);
bt_pre.setOnClickListener(this);
bt_last.setOnClickListener(this);
bt_next.setOnClickListener(this);
//设置文本大小
bt_first.setTextSize(12);
bt_pre.setTextSize(12);
bt_last.setTextSize(12);
bt_next.setTextSize(12);
tv_page.setTextSize(12);
//添加到底部容器
bottomLayout.addView(bt_first);
bottomLayout.addView(bt_pre);
bottomLayout.addView(bt_next);
bottomLayout.addView(bt_last);
bottomLayout.addView(tv_page);
bottomLayout.addView(sp_page);
}
//设置显示大小
public void setSize(View v) {
v.setLayoutParams(new android.view.ViewGroup.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
}
/**
* 翻页点击事件
*/
@Override
public void onClick(View v) {
if(v == bt_first) { //第一页
pageID = 0;
}else if(v == bt_last) { //最后一页
if(pageCount == 0) {
return;
}
pageID = pageCount;
}else if(v == bt_next) { //下一页
if(pageID < pageCount) {
++pageID;
} else {
return;
}
}else if(v == bt_pre) { //上一页
if(pageID <= 0){
return;
}else {
--pageID;
}
}
sp_page.setSelection(pageID);
}
/**
* 页码下拉框选择事件
*/
@Override
public void onItemSelected(AdapterView<?> arg0, View arg1, int arg2,
long arg3) {
pageID = arg2;
Log.e("onItemSelected:", "selected");
toPage(pageID * TableRowCount, this.sql);
}
@Override
public void onNothingSelected(AdapterView<?> arg0) {
// TODO Auto-generated method stub
}
/**
* 跳转页面
* @param stratIndex 开始页码
* @param sql 查询语句
*/
public void toPage(int stratIndex, String sql) {
//查询语句
sql += " Limit " + TableRowCount + " Offset " + stratIndex;
//获取查询结果集合
dataList = SQLiteUtility.query2(context, sql, fields);
//设置适配器
SimpleAdapter simpleAdapter = new SimpleAdapter(context, dataList,
R.layout.items, new String[]{"item"}, new int[] {R.id.ItemText});
gv_body.setAdapter(simpleAdapter); //重新添加适配器
}
/**
* 数据项点击事件
*/
@Override
public void onItemClick(AdapterView<?> arg0, View arg1, int arg2, long arg3) {
Toast.makeText(context, ((HashMap<String, String>)dataList.get(arg2)).get("item"),
Toast.LENGTH_SHORT).show();
}
}
4、SQLite操作类:SQLiteUtility
package com.myandroid.test;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import android.app.ActivityGroup;
import android.app.AlertDialog;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.util.Log;
import android.widget.Toast;
import android.database.Cursor;
import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase;
public class SQLiteUtility{
private static final int MODE_PRIVATE = 0x0;
private static final String DATABASE = "myDB2";
private static SQLiteDatabase db;
/**
* 插入一些数据
*/
public static void insertSomething(Context context) {
Cursor cursor;
int count = 0;
String sql = "CREATE TABLE myTable (id int not null, " +
"name text not null," +
"time text not null );";
SimpleDateFormat bartDateFormat =
new SimpleDateFormat("yyyy-MM-dd-HH:mm");
Date date = new Date();
try {
db = context.openOrCreateDatabase(DATABASE, MODE_PRIVATE, null);
String sqlCheckExsit = "select count(*) as c from Sqlite_master where type ='table' and name ='myTable' ";
cursor = db.rawQuery(sqlCheckExsit, null);
if(cursor.moveToNext()){
count = cursor.getInt(0);
if(count <= 0){
db.execSQL(sql);
}else {
db.execSQL("drop table myTable");
db.execSQL(sql);
}
}
for(int i = 0; i <30; i++) {
String insertSql = "insert into myTable ("
+ "id, name, time) values('" + i + "', 'admin','"
+ bartDateFormat.format(date) + "');";
db.execSQL(insertSql);
}
Log.e("insertSql", "ok");
}finally {
db.close();
}
}
/**
* 查询
* @param context 上下文
* @param sql SQl查询语句
* @param fields 字段名集合
* @return 查询结果集 List<String>类型
*/
public static List<String> query(Context context, String sql, String[] fields) {
List<String> dataList = new ArrayList<String>();
Cursor cursor;
try {
db = context.openOrCreateDatabase(DATABASE, MODE_PRIVATE, null);
cursor = db.rawQuery(sql, null);
if (cursor != null) {
while (cursor.moveToNext()) {
for (int i = 0; i < fields.length; i++) {
String temp = cursor.getString(cursor
.getColumnIndex(fields[i]));
dataList.add(temp);
}
}
}
}catch(Exception e) {
new AlertDialog.Builder(context)
.setIcon(android.R.drawable.ic_dialog_alert)
.setTitle("数据库连接错误:")
.setMessage("数据访问异常。")
.show();
} finally {
db.close();
}
return dataList;
}
/**
* 数据记录总条数
* @param context 上下文
* @param sql SQL查询语句
* @return 记录条数
*/
public static int getCount(Context context, String sql) {
int totalCounty = 0;
try {
db = context.openOrCreateDatabase(DATABASE, MODE_PRIVATE, null);
Cursor cursor = db.rawQuery(sql, null);
cursor.moveToFirst();
totalCounty = cursor.getInt(0);
} catch (Exception e) {
new AlertDialog.Builder(context)
.setIcon(android.R.drawable.ic_dialog_alert)
.setTitle("数据库连接错误:").setMessage("数据访问异常。").show();
} finally {
db.close();
}
return totalCounty;
}
/**
* 查询
* @param context 上下文
* @param sql SQl查询语句
* @param fields 字段名集合
* @return 查询结果集 ArrayList<HashMap<String,String>>类型
*/
public static ArrayList<HashMap<String,String>> query2(Context context, String sql, String[] fields) {
ArrayList<HashMap<String, String>> dataList = new ArrayList<HashMap<String, String>>();
Cursor cursor; //游标
try{
db = context.openOrCreateDatabase(DATABASE, MODE_PRIVATE, null); //连接数据库
cursor = db.rawQuery(sql, null); //获取数据集游标
if (cursor != null) {
while (cursor.moveToNext()) { //游标递增,访问数据集
for (int i = 0; i < fields.length; i++) {
String temp = cursor.getString(cursor //获取对应数据项
.getColumnIndex(fields[i]));
HashMap<String, String> map = new HashMap<String, String>();
map.put("item", temp);
dataList.add(map);
}
}
}
}catch(Exception e) {
new AlertDialog.Builder(context)
.setIcon(android.R.drawable.ic_dialog_alert)
.setTitle("数据库连接错误:")
.setMessage("数据访问异常。")
.show();
}finally {
cursor = null;
db.close();
}
return dataList;
}
}