Android之SQLite分页表格

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

<?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>

main.xml的代码如下:

<?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:layout_height="wrap_content"
		android:layout_width="fill_parent" android:id="@+id/btnCreateDB"
		android:text="创建数据库"></Button>
	<Button android:layout_height="wrap_content"
		android:layout_width="fill_parent" android:text="插入一串实验数据" android:id="@+id/btnInsertRec"></Button>
	<Button android:layout_height="wrap_content" android:id="@+id/btnClose"
		android:text="关闭数据库" android:layout_width="fill_parent"></Button>
</LinearLayout>

演示程序testSQLite.java的源码:

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的源码:

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);
	}
}


源码下载


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值