Android กับ ListView แสดงข้อมูลจาก Database ของ SQLite |
Android ListView กับ Database ของ SQLite ในการเขียนโปรแกรมบน Android เพื่อแสดงผลข้อมูลต่าง ๆ บน Activity Form ที่ทำงานคู่กับ XML Layout สิ่งทีเราจะได้พบเจอและจำเป็นจะต้องใช้ก็คือ ListView Widgets เพราะ ListView จะเข้ามาช่วยจัดการกับการแสดงข้อมูลในรูปแบบของตาราง แสดงข้อมูลแต่ล่ะแถว และแต่ล่ะ Column โดย ListView สามารถทำงานกับข้อมูลชนิดต่าง ๆ ได้หลากหลาย เช่น String ที่อยู่ในรูปแบบของ Array , ArrayList หรือ ข้อมูลจาก SQLite ที่อยู่ในรูปแบบของ Cursor ก็สามารถใช้ DataAdapter() แปลงข้อมูลเหล่านี้ ให้สามารถแสดงผลบน ListView ได้ ในความสามารถของ ListView สามารถกำหนดการแสดงผลแบบ Custom Column Layout คือสร้างจำนวน Column และกำหนดเงื่อนไขการแสดงผลต่าง ๆ ได้
Screenshot
แสดงรายการข้อมูลของ SQLite บน ListView
การสร้าง Popup เพื่อแสดงรายละเอียด
การสร้าง Context Menu แบบ Dialog Popup Command
โครงสร้างตารางและข้อมูล
ชื่อว่าตาราง members ประกอบด้วยฟิวด์ MemberID, Name , Tel
มีข้อมูลอยู่ 4 รายการ
หลังจากที่เรามีแหล่งข้อมูลของ SQLite เราสามารถทำการอ่านข้อมูลเหล่านี้มาเก็บไว้ในรูปแบบของ ArrayList แบบ HashMap ที่ประกอบด้วย Key และ Values ที่มีหลาย Index (เท่ากับจำนวน Rows แถวของข้อมูล)
// Show All Data
public ArrayList<HashMap<String, String>> SelectAllData() {
// TODO Auto-generated method stub
try {
ArrayList<HashMap<String, String>> MyArrList = new ArrayList<HashMap<String, String>>();
HashMap<String, String> map;
SQLiteDatabase db;
db = this.getReadableDatabase(); // Read Data
String strSQL = "SELECT * FROM " + TABLE_MEMBER;
Cursor cursor = db.rawQuery(strSQL, null);
if(cursor != null)
{
if (cursor.moveToFirst()) {
do {
map = new HashMap<String, String>();
map.put("MemberID", cursor.getString(0));
map.put("Name", cursor.getString(1));
map.put("Tel", cursor.getString(2));
MyArrList.add(map);
} while (cursor.moveToNext());
}
}
cursor.close();
db.close();
return MyArrList;
} catch (Exception e) {
return null;
}
}
จากวิธีข้างต้น จะเห็รว่ามีการประกาศ method ชนิด ArrayList<HashMap<String, String>> โดยในตัวแปร ArrayList ประกอบด้วย Key ที่มีชื่อว่า MemberID, Name, Tel แลังหลังจากที่ทำการ put ค่าทั้งหมดลงใน ArrayList แล้ว เราสามารถทำการตัดการเชื่อมต่อกับ Database ด้วย db.close(); และ return ค่า ArrayList กลับไปยัง function ที่มีการเรียกใช้ method นี้
ในฝั่งของการอ่านค่าตัวแปร ArrayList สามารถทำการ new class และเรียก method ตามตัวอย่าง
ArrayList<HashMap<String, String>> MebmerList;
// get Data from SQLite
myDBClass myDb = new myDBClass(this);
MebmerList = myDb.SelectAllData();
// listView1
ListView lisView1 = (ListView)findViewById(R.id.listView1);
SimpleAdapter sAdap;
sAdap = new SimpleAdapter(MainActivity.this, MebmerList, R.layout.activity_column,
new String[] {"MemberID", "Name", "Tel"}, new int[] {R.id.ColMemberID, R.id.ColName, R.id.ColTel});
lisView1.setAdapter(sAdap);
จากตัวอย่างจะเห็นว่ามีการประกาศตัวแปร MebmerList แบบ ArrayList<HashMap<String, String>> และรับค่าที่ได้จากการ return ของ method SelectAllData(); จากนั้นนำ ArrayList ที่ได้เข้า method ของ SimpleAdapter() เพื่อแปลงข้อมูลและแสดงผลบน ListView ที่มี Custom Layout อยู่ใน activity_column.xml
Code ทั้งหมด
ไฟล์ XML Layout ของ Activity หลัก
activity_main.xml
<TableLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/tableLayout1"
android:layout_width="fill_parent"
android:layout_height="fill_parent" >
<TableRow
android:id="@+id/tableRow1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="5dip" >
<TextView
android:id="@+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:gravity="center"
android:text="List Member : "
android:layout_span="1"
android:textAppearance="?android:attr/textAppearanceLarge" />
</TableRow>
<View
android:layout_height="1dip"
android:background="#CCCCCC" />
<LinearLayout
android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_weight="0.1">
<ListView
android:id="@+id/listView1"
android:layout_width="match_parent"
android:layout_height="wrap_content">
</ListView>
</LinearLayout>
<View
android:layout_height="1dip"
android:background="#CCCCCC" />
<LinearLayout
android:id="@+id/LinearLayout1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="5dip" >
<TextView
android:id="@+id/textView2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="By.. ThaiCreate.Com" />
</LinearLayout>
</TableLayout>
ไฟล์ XML Layout Custom Comlumn Layout ของ ListView
activity_column.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/linearLayout1"
android:layout_width="fill_parent"
android:layout_height="fill_parent" >
<TextView
android:id="@+id/ColMemberID"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="MemberID"/>
<TextView
android:id="@+id/ColName"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="2"
android:text="Name"/>
<TextView
android:id="@+id/ColTel"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="Tel" />
</LinearLayout>
ไฟล์สำหรับติดต่อกลับฐานข้อมูล
myDBClass.java
package com.myapp;
import java.util.ArrayList;
import java.util.HashMap;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.util.Log;
public class myDBClass extends SQLiteOpenHelper {
// Database Version
private static final int DATABASE_VERSION = 1;
// Database Name
private static final String DATABASE_NAME = "mydatabase";
// Table Name
private static final String TABLE_MEMBER = "members";
public myDBClass(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
// TODO Auto-generated constructor stub
}
@Override
public void onCreate(SQLiteDatabase db) {
// TODO Auto-generated method stub
// Create Table Name
db.execSQL("CREATE TABLE " + TABLE_MEMBER +
"(MemberID INTEGER PRIMARY KEY AUTOINCREMENT," +
" Name TEXT(100)," +
" Tel TEXT(100));");
Log.d("CREATE TABLE","Create Table Successfully.");
}
// Show All Data
public ArrayList<HashMap<String, String>> SelectAllData() {
// TODO Auto-generated method stub
try {
ArrayList<HashMap<String, String>> MyArrList = new ArrayList<HashMap<String, String>>();
HashMap<String, String> map;
SQLiteDatabase db;
db = this.getReadableDatabase(); // Read Data
String strSQL = "SELECT * FROM " + TABLE_MEMBER;
Cursor cursor = db.rawQuery(strSQL, null);
if(cursor != null)
{
if (cursor.moveToFirst()) {
do {
map = new HashMap<String, String>();
map.put("MemberID", cursor.getString(0));
map.put("Name", cursor.getString(1));
map.put("Tel", cursor.getString(2));
MyArrList.add(map);
} while (cursor.moveToNext());
}
}
cursor.close();
db.close();
return MyArrList;
} catch (Exception e) {
return null;
}
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
// TODO Auto-generated method stub
db.execSQL("DROP TABLE IF EXISTS " + TABLE_MEMBER);
// Re Create on method onCreate
onCreate(db);
}
}
ไฟล์ Java Activity หลักที่ทำงานควบคุมการทำงานต่าง ๆ
MainActivity.java
package com.myapp;
import java.util.ArrayList;
import java.util.HashMap;
import android.os.Bundle;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ListView;
import android.widget.SimpleAdapter;
import android.widget.Toast;
import android.app.Activity;
public class MainActivity extends Activity {
ArrayList<HashMap<String, String>> MebmerList;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// get Data from SQLite
myDBClass myDb = new myDBClass(this);
MebmerList = myDb.SelectAllData();
// listView1
ListView lisView1 = (ListView)findViewById(R.id.listView1);
SimpleAdapter sAdap;
sAdap = new SimpleAdapter(MainActivity.this, MebmerList, R.layout.activity_column,
new String[] {"MemberID", "Name", "Tel"}, new int[] {R.id.ColMemberID, R.id.ColName, R.id.ColTel});
lisView1.setAdapter(sAdap);
// OnClick Item
lisView1.setOnItemClickListener(new OnItemClickListener() {
public void onItemClick(AdapterView<?> myAdapter, View myView, int position, long mylng) {
String MemberID = MebmerList.get(position).get("MemberID").toString();
Toast.makeText(getApplicationContext(),
"Selected MemberID : " + MemberID, Toast.LENGTH_SHORT).show();
}
});
}
}
Screenshot
แสดงผลข้อมูลบน ListView แบบหลาย Column จาก SQLite Database
การสร้าง Dialog Popup เพื่อแสดงรายละเอียดของรายการที่เลือก
หลังจากที่เรานำข้อมูลจาก SQLite แสดงบน ListView ได้แล้ว ลองเขียนความสามารถอื่น ๆ ให้กับ ListView เช่น เมื่อคลิกที่รายการ ให้แสดง Popup Dialog เพื่อแสดงรายละเอียดของรายการในแถวนั้น ๆ
แสดงรายละเอียดบน Popup Dailog
// OnClick Item
lisView1.setOnItemClickListener(new OnItemClickListener() {
public void onItemClick(AdapterView<?> myAdapter, View myView, int position, long mylng) {
String sMemberID = MebmerList.get(position).get("MemberID").toString();
String sName = MebmerList.get(position).get("Name").toString();
String sTel = MebmerList.get(position).get("Tel").toString();
viewDetail.setIcon(android.R.drawable.btn_star_big_on);
viewDetail.setTitle("Member Detail");
viewDetail.setMessage("MemberID : " + sMemberID + "\n"
+ "Name : " + sName + "\n"
+ "Tel : " + sTel);
viewDetail.setPositiveButton("OK",
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
// TODO Auto-generated method stub
dialog.dismiss();
}
});
viewDetail.show();
}
});
การเพิ่ม Dialog สามารถทำได้ไม่ยาก ด้ววยการกำหนดคุณสมบัติที่ method ของ setOnItemClickListener() หลังจากนั้นก็ใช้ method ของ AlertDialog() กำหนดครายละเอียดและคุณสมบัติของ Popup Dialog
MainActivity.java
package com.myapp;
import java.util.ArrayList;
import java.util.HashMap;
import android.os.Bundle;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ListView;
import android.widget.SimpleAdapter;
import android.widget.Toast;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
public class MainActivity extends Activity {
ArrayList<HashMap<String, String>> MebmerList;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// get Data from SQLite
myDBClass myDb = new myDBClass(this);
MebmerList = myDb.SelectAllData();
// listView1
ListView lisView1 = (ListView)findViewById(R.id.listView1);
SimpleAdapter sAdap;
sAdap = new SimpleAdapter(MainActivity.this, MebmerList, R.layout.activity_column,
new String[] {"MemberID", "Name", "Tel"}, new int[] {R.id.ColMemberID, R.id.ColName, R.id.ColTel});
lisView1.setAdapter(sAdap);
// Dialog
final AlertDialog.Builder viewDetail = new AlertDialog.Builder(this);
// OnClick Item
lisView1.setOnItemClickListener(new OnItemClickListener() {
public void onItemClick(AdapterView<?> myAdapter, View myView, int position, long mylng) {
String sMemberID = MebmerList.get(position).get("MemberID").toString();
String sName = MebmerList.get(position).get("Name").toString();
String sTel = MebmerList.get(position).get("Tel").toString();
viewDetail.setIcon(android.R.drawable.btn_star_big_on);
viewDetail.setTitle("Member Detail");
viewDetail.setMessage("MemberID : " + sMemberID + "\n"
+ "Name : " + sName + "\n"
+ "Tel : " + sTel);
viewDetail.setPositiveButton("OK",
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
// TODO Auto-generated method stub
dialog.dismiss();
}
});
viewDetail.show();
}
});
}
}
Screenshot
แสดง Popup Dialog เมื่อคลิกที่รายการ ตามภาพ Screenshot
การสร้าง Context Menu แบบ Dialog Popup Command
การเพิ่มคุณสมบัติ Context Menu เพื่อสร้าง Dialog Popup Command เช่น Edit, Delete, Hide โดย Event จะเกิดขึ้นต่อเมื่อมีการคลิกที่รายการค้างประมาณ 1 วินาที หรือ Long Click - onLongPress
การแสดง Dialog Popup Command บน Context Menu
ในการสร้าง Content Menu นั้นขั้นแรกจะต้องประกาศ Array ที่จะสร้าง Command
String[] Cmd = {"Edit","Delete","Hide"};
ประกาศตัวแปน Command
registerForContextMenu(lisView1);
ประกาศเรียกใช้ ContextMenu สำหรับ ListView
การประกาศ method สำหรับสร้าง Context Menu จะใช้ method ที่มีชื่อว่า onCreateContextMenu() และ method ที่จะใช้ในการอ่านรายการ Command ที่เลือกคือ onContextItemSelected()
@Override
public void onCreateContextMenu(ContextMenu menu, View v,
ContextMenuInfo menuInfo) {
AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo)menuInfo;
menu.setHeaderIcon(android.R.drawable.btn_star_big_on);
menu.setHeaderTitle("Command for : [" + MebmerList.get(info.position).get("Name").toString() + "]");
String[] menuItems = Cmd;
for (int i = 0; i<menuItems.length; i++) {
menu.add(Menu.NONE, i, i, menuItems[i]);
}
}
@Override
public boolean onContextItemSelected(MenuItem item) {
AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo)item.getMenuInfo();
int menuItemIndex = item.getItemId();
String[] menuItems = Cmd;
String CmdName = menuItems[menuItemIndex];
String MemID = MebmerList.get(info.position).get("MemberID").toString();;
// Check Event Command
if ("Edit".equals(CmdName)) {
Toast.makeText(MainActivity.this,"Edit Command (MemberID = " + MemID + ")",Toast.LENGTH_LONG).show();
} else if ("Delete".equals(CmdName)) {
Toast.makeText(MainActivity.this,"Delete Command (MemberID = " + MemID + ")",Toast.LENGTH_LONG).show();
} else if ("Hide".equals(CmdName)) {
Toast.makeText(MainActivity.this,"Hide Command (MemberID = " + MemID + ")",Toast.LENGTH_LONG).show();
}
return true;
}
จะเห็นว่ามี method ของ onContextItemSelected() มีการกำหนดเงื่อนไขว่าแต่ล่ะ Command จะให้ทำอะไรบ้าง
// Check Event Command
if ("Edit".equals(CmdName)) {
Toast.makeText(MainActivity.this,"Edit Command (MemberID = " + MemID + ")",Toast.LENGTH_LONG).show();
} else if ("Delete".equals(CmdName)) {
Toast.makeText(MainActivity.this,"Delete Command (MemberID = " + MemID + ")",Toast.LENGTH_LONG).show();
} else if ("Hide".equals(CmdName)) {
Toast.makeText(MainActivity.this,"Hide Command (MemberID = " + MemID + ")",Toast.LENGTH_LONG).show();
}
MainActivity.java
package com.myapp;
import java.util.ArrayList;
import java.util.HashMap;
import android.os.Bundle;
import android.view.ContextMenu;
import android.view.ContextMenu.ContextMenuInfo;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ListView;
import android.widget.SimpleAdapter;
import android.widget.Toast;
import android.app.Activity;
public class MainActivity extends Activity {
String[] Cmd = {"Edit","Delete","Hide"};
ArrayList<HashMap<String, String>> MebmerList;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// get Data from SQLite
myDBClass myDb = new myDBClass(this);
MebmerList = myDb.SelectAllData();
// listView1
ListView lisView1 = (ListView)findViewById(R.id.listView1);
SimpleAdapter sAdap;
sAdap = new SimpleAdapter(MainActivity.this, MebmerList, R.layout.activity_column,
new String[] {"MemberID", "Name", "Tel"}, new int[] {R.id.ColMemberID, R.id.ColName, R.id.ColTel});
lisView1.setAdapter(sAdap);
registerForContextMenu(lisView1);
}
@Override
public void onCreateContextMenu(ContextMenu menu, View v,
ContextMenuInfo menuInfo) {
AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo)menuInfo;
menu.setHeaderIcon(android.R.drawable.btn_star_big_on);
menu.setHeaderTitle("Command for : [" + MebmerList.get(info.position).get("Name").toString() + "]");
String[] menuItems = Cmd;
for (int i = 0; i<menuItems.length; i++) {
menu.add(Menu.NONE, i, i, menuItems[i]);
}
}
@Override
public boolean onContextItemSelected(MenuItem item) {
AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo)item.getMenuInfo();
int menuItemIndex = item.getItemId();
String[] menuItems = Cmd;
String CmdName = menuItems[menuItemIndex];
String MemID = MebmerList.get(info.position).get("MemberID").toString();;
// Check Event Command
if ("Edit".equals(CmdName)) {
Toast.makeText(MainActivity.this,"Edit Command (MemberID = " + MemID + ")",Toast.LENGTH_LONG).show();
} else if ("Delete".equals(CmdName)) {
Toast.makeText(MainActivity.this,"Delete Command (MemberID = " + MemID + ")",Toast.LENGTH_LONG).show();
} else if ("Hide".equals(CmdName)) {
Toast.makeText(MainActivity.this,"Hide Command (MemberID = " + MemID + ")",Toast.LENGTH_LONG).show();
}
return true;
}
}
Screenshot
แสดง Context Menu แบบ Command
แสดงข้อความเมื่อเลือกคำสั่งนั้น ๆ ทั้งนี้สามารถเขียนคำสั่งอื่น ๆ หลังจากที่ทำงานแล้ว
ตัวอย่างการใช้ Command Context Menu
Go to : Android Delete Rows Data in SQLite Database (Android SQLite)
ListView - Android Widgets Example
Android ListView and SQLite Database (Android SQLite)
Android ListView แบบ Custom Layout แสดงข้อมูล ListView หลายคอลัมบ์ Multiple Column
|