編輯:Android開發實例
繼前一篇文章講到Android上的SQLite分頁讀取,其功能只是用文本框顯示數據而已。本文就講得更加深入些,實現並封裝一個SQL分頁表格控件,不僅支持分頁還是以表格的形式展示數據。
先來看看本文程序運行的動畫如下圖所示:
這個SQL分頁表格控件主要分為“表格區”和“分頁欄”這兩部分,這兩部分都是基於GridView實現的。網上介紹Android上實現表格的DEMO一般都用ListView。ListView與GridView對比,ListView最大的優勢是格單元的大小可以自定義,可以某單元長某單元短,但是難於實現自適應數據表的結構;而GridView最大的優勢就是自適應數據表的結構,但是格單元統一大小。對於數據表結構多變的情況,建議使用GridView實現表格。
本文實現的SQL分頁表格控件有以下特點:
1.自適應數據表結構,但是格單元統一大小;
2.支持分頁;
3.“表格區”有按鍵事件回調處理,“分頁欄”有分頁切換事件回調處理。
本文程序代碼較多,可以到這裡下載整個工程的源碼:http://xiazai.jb51.net/201408/yuanma/testSQLite(jb51.bet).rar
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); } }
希望本文所述實例對於大家進行Android項目開發能起到參考借鑒作用。
登錄應用程序的屏幕,詢問憑據登錄到一些特定的應用。可能需要登錄到Facebook,微博等本章介紹了,如何創建一個登錄界面,以及如何管理安全問題和錯誤嘗試。首先,必須定義兩
學習目的: 1、掌握在Android中如何建立CheckBox 2、掌握CheckBox的常用屬性 3、掌握CheckBox選中狀態變換的事件(監聽器) Chec
本文實例講述了使用SAX來解析XML。通常來說在Android裡面可以使用SAX和DOM,DOM需要把整個XML文件讀入內存再解析,比較消耗內存,而SAX是基於事
本文實例講述了Android編程實現QQ表情的發送和接收。分享給大家供大家參考,具體如下: 在自己做一個聊天應用練習的時候,需要用到表情,於是就想著模仿一下QQ表