有關ListView使用的adapter,上面是其類別圖。希望不要有錯才好...
有關UML的內容,可以參考這裡(淺談UML)或是這裡(六大關係)。
然後小書做了一個Demo,是將一些常用的adapter實做出來,可以從這裡下載。
然後,寫到這裡竟然只有三行?!來把Demo裡面的code貼出來吧...
首先,因為我把Database放SD卡裡面,所以我們必需要增加權限:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="adapter.susan.idea"
android:versionCode="1"
android:versionName="1.0"
android:installLocation="preferExternal">
<uses-sdk android:minSdkVersion="8" />
<application
android:icon="@drawable/ic_launcher"
android:label="@string/app_name" >
<activity
android:label="@string/app_name"
android:name=".Main" >
<intent-filter >
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
</manifest>
然後,把相關的layout做出來,主要有兩種對應的畫面和主畫面的layout,
主畫面main.xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<Spinner
android:id="@+id/Spinner"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
/>
<ListView
android:id="@+id/ListView"
android:layout_width="fill_parent"
android:layout_height="fill_parent" />
</LinearLayout>
第一種row_list.xml和第二種row_list1.xml對應的畫面其實差不多,沒什麼太大的意義:
<linearlayout android:id="@+id/widget31" android:layout_height="fill_parent" android:layout_width="fill_parent" android:orientation="vertical" xmlns:android="http://schemas.android.com/apk/res/android">
<linearlayout android:id="@+id/widget32" android:layout_height="wrap_content" android:layout_width="fill_parent">
<textview android:gravity="center" android:id="@+id/textView1" android:layout_height="wrap_content" android:layout_weight="0.2" android:layout_width="wrap_content" android:text="TextView">
</textview>
<textview android:gravity="center" android:id="@+id/textView2" android:layout_height="wrap_content" android:layout_weight="1" android:layout_width="wrap_content" android:text="TextView">
</textview>
</linearlayout>
<linearlayout android:id="@+id/linearLayout2" android:layout_height="wrap_content" android:layout_width="match_parent">
<linearlayout android:id="@+id/linearLayout1" android:layout_height="wrap_content" android:layout_weight="1" android:layout_width="match_parent" android:orientation="vertical">
<textview android:gravity="center" android:id="@+id/textView3" android:layout_height="wrap_content" android:layout_width="match_parent" android:text="Large Text" android:textappearance="?android:attr/textAppearanceLarge">
<textview android:gravity="center" android:id="@+id/textView4" android:layout_height="wrap_content" android:layout_width="match_parent" android:text="Medium Text" android:textappearance="?android:attr/textAppearanceMedium">
</textview></textview></linearlayout>
</linearlayout>
</linearlayout>
<linearlayout android:id="@+id/widget31" android:layout_height="fill_parent" android:layout_width="fill_parent" android:orientation="vertical" xmlns:android="http://schemas.android.com/apk/res/android">
<linearlayout android:id="@+id/widget32" android:layout_height="wrap_content" android:layout_width="fill_parent">
<textview android:gravity="center" android:id="@+id/textView1" android:layout_height="wrap_content" android:layout_weight="0.2" android:layout_width="wrap_content" android:text="TextView">
</textview>
<textview android:gravity="center" android:id="@+id/textView2" android:layout_height="wrap_content" android:layout_weight="1" android:layout_width="wrap_content" android:text="TextView">
</textview>
</linearlayout>
<linearlayout android:id="@+id/linearLayout2" android:layout_height="wrap_content" android:layout_width="fill_parent">
<linearlayout android:id="@+id/linearLayout1" android:layout_height="wrap_content" android:layout_weight="0.7" android:layout_width="0dp" android:orientation="vertical">
<textview android:gravity="center" android:id="@+id/textView3" android:layout_height="wrap_content" android:layout_width="match_parent" android:text="Large Text" android:textappearance="?android:attr/textAppearanceLarge">
<textview android:gravity="center" android:id="@+id/textView4" android:layout_height="wrap_content" android:layout_width="match_parent" android:text="Medium Text" android:textappearance="?android:attr/textAppearanceMedium">
</textview></textview></linearlayout>
<imageview android:id="@+id/imageView1" android:layout_height="fill_parent" android:layout_weight="0.3" android:layout_width="0dp" android:src="@android:drawable/ic_menu_mapmode">
</imageview></linearlayout>
</linearlayout>
然後就是DataBase的class了,是拿之前上課的class出來修修修改改改,參考自這裡:
update:4/8 修改了class裡面其中一個方法,檔案裡面沒有改過來:
/** 依照時間間隔獲取資料 */
public Cursor getIntervalData(Timestamp from, Timestamp to) {
String cmd = "SELECT * FROM " + TABLE + " WHERE (" + KEY_COLUMNS[0]
+ " >= '" + from.toString() + "') AND (" + KEY_COLUMNS[0]
+ " <= '" + to.toString() + "')";
return db.rawQuery(cmd, null);
}
package adapter.susan.idea;
import java.sql.Timestamp;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.util.Log;
public class DB {
private static final String TAG = DB.class.getSimpleName();
static final int VERSION = 1;
static final String DATABASE = android.os.Environment
.getExternalStorageDirectory().getAbsolutePath() +"/DataBaseBABABA/databaseTest.db3";
static final String TABLE = "tableOfthisDataBase";
/**
* { "date", "value", "value2" }
*/
public static final String[] KEY_COLUMNS = { "date", "value",
"value2" };
// //建立資料庫欄位格式
// public static String createSQL ;
// DbHelper implementations, 宣告成為靜態
// DbHelper類別為sqliteDB類別的內隱類別(inner class)
// 加上static關鍵字,DbHelper就變成sqliteDB類別的巢狀類別(nested class)
private static class DbHelper extends SQLiteOpenHelper {
public DbHelper(Context context) {
super(context, DATABASE, null, VERSION);
}
@Override
// 只會被呼叫一次,在第一次資料庫建立的時候
public void onCreate(SQLiteDatabase db) {
// TODO Auto-generated method stub
Log.i(TAG, "Creating database: " + DATABASE);
db.execSQL(getCreateSQL());
}
public String getCreateSQL() {
StringBuffer mStringBuffer = new StringBuffer();
mStringBuffer.append("CREATE TABLE IF NOT EXISTS " + TABLE + " ("
+ "_id"
+ " INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, "
+ KEY_COLUMNS[0]
+ " TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,");
for (int n = 1; n < KEY_COLUMNS.length; n++) {
mStringBuffer.append(KEY_COLUMNS[n] + " TEXT, ");
}
mStringBuffer.delete(mStringBuffer.length() - 2,
mStringBuffer.length());// 刪除", "
mStringBuffer.append(");");
return mStringBuffer.toString();
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
// TODO Auto-generated method stub
db.execSQL("DROP TABLE IF EXISTS " + TABLE);
this.onCreate(db);
}
}
// instance of dbHelper
private final DbHelper dbHelper; // 不希望被改變
private SQLiteDatabase db;
public DB(Context context) {
dbHelper = new DbHelper(context);
Log.i(TAG, "Initialized database in Constructor of DB");
}
public DB openToWrite() throws SQLException {
db = dbHelper.getWritableDatabase(); // 若資料庫存在則開啟;若不存在則建立一個新的
return this;
}
public DB openToRead() throws SQLException {
db = dbHelper.getReadableDatabase(); // 若資料庫存在則開啟;若不存在則建立一個新的
return this;
}
public void close() {
dbHelper.close();
}
/** 添加資料 */
public void insert(ContentValues values) throws SQLException {
// db.insertWithOnConflict(TABLE, null, values,
// SQLiteDatabase.CONFLICT_IGNORE); //這個指令需要And 2.2以上版本
db.insertOrThrow(TABLE, null, values); // 如果插入錯誤會丟一個例外出來,暫不處理。
Log.i(TAG, "insert data into db");
}
/**
* 更新資料(測試)
*
* @param column
* 輸入欄位名稱
* @param oldValue
* 輸入欄位內欲查詢的變數
* @param newValue
* 輸入要更新的值
*/
public void update(String column, String oldValue, ContentValues newValue)
throws SQLException {
db.update(TABLE, newValue, column + "=" + oldValue, null);
}
/**
* 刪除資料(測試)
*
* @param column
* 輸入欄位名稱
* @param value
* 輸入欄位內欲查詢的變數
*/
public void deleteData(String column, String value) throws SQLException {
db.delete(TABLE, column + "=" + value, null);
}
/**
* 獲得資料(測試)
*
* @param column
* 輸入欄位名稱
* @param value
* 輸入欄位內欲查詢的變數
*/
public Cursor getData(String column, String value) {
String cmd = "SELECT * FROM " + TABLE + " WHERE " + column + "="
+ value;
return db.rawQuery(cmd, null);
}
/** 獲得全部資料 */
public Cursor getAll() {
// return db.rawQuery("SELECT * FROM " + TABLE, null);
return db.query(TABLE, null, null, null, null, null, null);
}
/** 依照時間間隔獲取資料 */
public Cursor getIntervalData(Timestamp from, Timestamp to) {
String cmd = "SELECT * FROM " + TABLE + " WHERE (" + KEY_COLUMNS[0]
+ " >= '" + from.toString() + "') AND (" + KEY_COLUMNS[0]
+ " <= '" + to.toString() + "')";
return db.rawQuery(cmd, null);
}
/** 清除全部的資料 */
public boolean clearAll() {
return db.delete(TABLE, null, null) > 0;
}
}
然後是主函式:
package adapter.susan.idea;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.HashMap;
import android.app.Activity;
import android.content.ContentValues;
import android.database.Cursor;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemSelectedListener;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.SimpleAdapter;
import android.widget.SimpleCursorAdapter;
import android.widget.SimpleCursorAdapter.ViewBinder;
import android.widget.Spinner;
import android.widget.TextView;
import android.widget.Toast;
public class Main extends Activity {
private ListView listView;
private Spinner spinner;// 切換ListView用的
private DB db;// 資料庫
private Cursor cursor = null;
/** ArrayAdapter顯示的字串,也是作為添加資料庫的的變數值 */
private final String[] mString = { "如何讓你遇見我", "在我最美麗的時刻 為這", "我已再佛前求了五百年",
"求祂讓我們結一段塵緣", "佛於是把我化成一棵樹", "長在你必經的路旁", "陽光下慎重地開滿花", "朵朵都是我前世的盼望",
"當你走近", "請你細聽", "那顫抖得葉是我等待的熱情", "而當你終於無視地走過", "在你身後落了一地的",
"朋友啊 那不是花辦 那是我凋零的心" };
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
init();
}
/** 變數初始化 */
private void init() {
listView = (ListView) this.findViewById(R.id.ListView);
spinner = (Spinner) this.findViewById(R.id.Spinner);
db = new DB(this);
db.openToWrite();
createData();
ArrayAdapter<String> adapter;// 做sprinner的adapter
adapter = new ArrayAdapter<String>(this,
android.R.layout.simple_spinner_item, new String[] {
"ArrayAdapter<String>", "SimpleAdapter",
"SimpleCursorAdapter",
"SimpleCursorAdapter,using ViewBinder" });
// 設置下拉菜單的風格
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
// 產生畫面
spinner.setAdapter(adapter);
Toast.makeText(this, "" + spinner.getAdapter().getClass().getName(),
Toast.LENGTH_LONG).show();
// 這邊會發現spinner的adapter抓出來的type是SpinnerAdapter
spinner.setOnItemSelectedListener(mOnItemSelectedListener);
}
/** show出ListView的畫面 */
private void showListView(int type) {
// ArrayAdapter<T>, HeaderViewListAdapter,SimpleAdapter,
// SimpleCursorAdapter,
// BaseAdapter,CursorAdapter,ResourceCursorAdapter 抽象的
// ListAdapter,SpinnerAdapter,WrapperListAdapter 介面
final int[] ID_VIEW = { R.id.textView1, R.id.textView3, R.id.textView2,
R.id.textView4 };// id,time,value1,value2.
final String[] KEY_COLUMN_NAME = { "_id", DB.KEY_COLUMNS[0],
DB.KEY_COLUMNS[1], DB.KEY_COLUMNS[2] };
switch (type) {
case 0:// 顯示ArrayAdapter所設定的畫面
Toast.makeText(this, "ArrayAdapter<String>", Toast.LENGTH_SHORT)
.show();
ArrayAdapter<String> mArrayAdapter = new ArrayAdapter<String>(this,
android.R.layout.simple_list_item_1, mString);
listView.setAdapter(mArrayAdapter);
break;
case 1:// 顯示SimpleAdapter所設定的畫面
/* 我們在這裡用database來做為資料來源,
* 這樣顯示的內容應該是跟SimpleCursorAdapter一樣的。
* 但是為了表現出SimpleAdapter的靈活,我們在HashMap<String, String>那邊動了些手腳。*/
Toast.makeText(this, "SimpleAdapter", Toast.LENGTH_SHORT).show();
cursor = db.getAll();
if (cursor.getCount() > 0) {
cursor.moveToFirst();
ArrayList<HashMap<String, String>> values = new ArrayList<HashMap<String, String>>();
int n = 0;
while (cursor.moveToNext()) {// 有很多方法可以移動cursor,這個算是目前比較簡便的方式
HashMap<String, String> item = new HashMap<String, String>();
item.put(KEY_COLUMN_NAME[0],
"SimpleAdapter" + String.valueOf(n));
/*在SimpleCursorAdapter裡面,KEY_COLUMN_NAME[0]會成為"_id"的內容,
* 不過我們把它改成了自定義的字串。如果要在SimpleCursorAdapter內實作一樣的效果,
* 則必須使用ViewBinder(見case 3)*/
for (String columnName : DB.KEY_COLUMNS) {
item.put(columnName, cursor.getString(cursor
.getColumnIndex(columnName)));
}
values.add(item);
n++;
}
SimpleAdapter mSimpleAdapter = new SimpleAdapter(this, values,
R.layout.row_list, KEY_COLUMN_NAME, ID_VIEW);
listView.setAdapter(mSimpleAdapter);
}
break;
case 2:// 顯示SimpleCursorAdapter所設定的畫面
Toast.makeText(this, "SimpleCursorAdapter", Toast.LENGTH_SHORT)
.show();
cursor = db.getAll();
if (cursor.getCount() > 0) {
// startManagingCursor(cursor);
SimpleCursorAdapter mSimpleCursorAdapter = new SimpleCursorAdapter(
this, R.layout.row_list, cursor, KEY_COLUMN_NAME,
ID_VIEW);
listView.setAdapter(mSimpleCursorAdapter);
}
break;
case 3:// 顯示SimpleCursorAdapter所設定的畫面,使用viewBinder的結果
Toast.makeText(this, "SimpleCursorAdapter ,use ViewBinder.",
Toast.LENGTH_SHORT).show();
cursor = db.getAll();
if (cursor.getCount() > 0) {
// startManagingCursor(cursor);
SimpleCursorAdapter mSimpleCursorAdapter = new SimpleCursorAdapter(
this, R.layout.row_list1, cursor, KEY_COLUMN_NAME,
ID_VIEW);
// Sets the binder used to bind data to views.
mSimpleCursorAdapter.setViewBinder(new ViewBinder() {
@Override
public boolean setViewValue(View view, Cursor cursor,
int columnIndex) {
// 設定view和cursor對應的內容
/*
* 参数view.getId()得到的值对应的不是实例化Adapter时传入的layout的ID。
* 实际对应的是实例化adapter里传入的参数int[] to里的值。
* 然后再由该值找到对应的View控件,进而改变相应的显示内容、样式等
*/
if (view.getId() == R.id.textView4) {
TextView mTextView = (TextView) view;
mTextView.setText("強制變身!登登!這是第"
+ cursor.getPosition() + "位置。");
Log.d("Test", "if(view.getId()==R.id.textView4)");
return true;
}
// Returns:
// true if the data was bound to the view, false
// otherwise
return false;
}
});
listView.setAdapter(mSimpleCursorAdapter);
}
break;
default:
showListView(0);
break;
}
}
OnItemSelectedListener mOnItemSelectedListener = new OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> parent, View view,
int position, long id) {
showListView(position);
}
@Override
public void onNothingSelected(AdapterView<?> parent) {
showListView(0);
}
};
@Override
public void onDestroy() {
super.onDestroy();
db.close();
if (cursor != null) {
cursor.close();
}
}
/** 產生測試用的data資料 */
private void createData() {
db.clearAll();// 做個清除的動作。
Calendar c = Calendar.getInstance();
Timestamp timestamp = new Timestamp(c.getTimeInMillis());
int n = 0;
while (n < mString.length) {
timestamp.setTime(timestamp.getTime() + 86399000 * n);
ContentValues values = new ContentValues();
// "2012-1-12 10:35:24"
values.put(DB.KEY_COLUMNS[0], timestamp.toString()); // 使用系統目前的時間
values.put(DB.KEY_COLUMNS[1], "第" + n + "句。");
values.put(DB.KEY_COLUMNS[2], mString[n]);
db.insert(values);
n++;
}
}
}
大概是這樣,最後附上SimpleCursorAdapter的源碼(2.2):
/*
* Copyright (C) 2006 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package android.widget;
import android.content.Context;
import android.database.Cursor;
import android.net.Uri;
import android.view.View;
/**
* An easy adapter to map columns from a cursor to TextViews or ImageViews
* defined in an XML file. You can specify which columns you want, which
* views you want to display the columns, and the XML file that defines
* the appearance of these views.
*
* Binding occurs in two phases. First, if a
* {@link android.widget.SimpleCursorAdapter.ViewBinder} is available,
* {@link ViewBinder#setViewValue(android.view.View, android.database.Cursor, int)}
* is invoked. If the returned value is true, binding has occured. If the
* returned value is false and the view to bind is a TextView,
* {@link #setViewText(TextView, String)} is invoked. If the returned value
* is false and the view to bind is an ImageView,
* {@link #setViewImage(ImageView, String)} is invoked. If no appropriate
* binding can be found, an {@link IllegalStateException} is thrown.
*
* If this adapter is used with filtering, for instance in an
* {@link android.widget.AutoCompleteTextView}, you can use the
* {@link android.widget.SimpleCursorAdapter.CursorToStringConverter} and the
* {@link android.widget.FilterQueryProvider} interfaces
* to get control over the filtering process. You can refer to
* {@link #convertToString(android.database.Cursor)} and
* {@link #runQueryOnBackgroundThread(CharSequence)} for more information.
*/
public class SimpleCursorAdapter extends ResourceCursorAdapter {
/**
* A list of columns containing the data to bind to the UI.
* This field should be made private, so it is hidden from the SDK.
* {@hide}
*/
protected int[] mFrom;
/**
* A list of View ids representing the views to which the data must be bound.
* This field should be made private, so it is hidden from the SDK.
* {@hide}
*/
protected int[] mTo;
private int mStringConversionColumn = -1;
private CursorToStringConverter mCursorToStringConverter;
private ViewBinder mViewBinder;
String[] mOriginalFrom;
/**
* Constructor the enables auto-requery.
*
* @deprecated This option is discouraged, as it results in Cursor queries
* being performed on the application's UI thread and thus can cause poor
* responsiveness or even Application Not Responding errors. As an alternative,
* use {@link android.app.LoaderManager} with a {@link android.content.CursorLoader}.
*/
@Deprecated
public SimpleCursorAdapter(Context context, int layout, Cursor c, String[] from, int[] to) {
super(context, layout, c);
mTo = to;
mOriginalFrom = from;
findColumns(from);
}
/**
* Standard constructor.
*
* @param context The context where the ListView associated with this
* SimpleListItemFactory is running
* @param layout resource identifier of a layout file that defines the views
* for this list item. The layout file should include at least
* those named views defined in "to"
* @param c The database cursor. Can be null if the cursor is not available yet.
* @param from A list of column names representing the data to bind to the UI. Can be null
* if the cursor is not available yet.
* @param to The views that should display column in the "from" parameter.
* These should all be TextViews. The first N views in this list
* are given the values of the first N columns in the from
* parameter. Can be null if the cursor is not available yet.
* @param flags Flags used to determine the behavior of the adapter,
* as per {@link CursorAdapter#CursorAdapter(Context, Cursor, int)}.
*/
public SimpleCursorAdapter(Context context, int layout, Cursor c, String[] from,
int[] to, int flags) {
super(context, layout, c, flags);
mTo = to;
mOriginalFrom = from;
findColumns(from);
}
/**
* Binds all of the field names passed into the "to" parameter of the
* constructor with their corresponding cursor columns as specified in the
* "from" parameter.
*
* Binding occurs in two phases. First, if a
* {@link android.widget.SimpleCursorAdapter.ViewBinder} is available,
* {@link ViewBinder#setViewValue(android.view.View, android.database.Cursor, int)}
* is invoked. If the returned value is true, binding has occured. If the
* returned value is false and the view to bind is a TextView,
* {@link #setViewText(TextView, String)} is invoked. If the returned value is
* false and the view to bind is an ImageView,
* {@link #setViewImage(ImageView, String)} is invoked. If no appropriate
* binding can be found, an {@link IllegalStateException} is thrown.
*
* @throws IllegalStateException if binding cannot occur
*
* @see android.widget.CursorAdapter#bindView(android.view.View,
* android.content.Context, android.database.Cursor)
* @see #getViewBinder()
* @see #setViewBinder(android.widget.SimpleCursorAdapter.ViewBinder)
* @see #setViewImage(ImageView, String)
* @see #setViewText(TextView, String)
*/
@Override
public void bindView(View view, Context context, Cursor cursor) {
final ViewBinder binder = mViewBinder;
final int count = mTo.length;
final int[] from = mFrom;
final int[] to = mTo;
for (int i = 0; i < count; i++) {
final View v = view.findViewById(to[i]);
if (v != null) {
boolean bound = false;
if (binder != null) {
bound = binder.setViewValue(v, cursor, from[i]);
}
if (!bound) {
String text = cursor.getString(from[i]);
if (text == null) {
text = "";
}
if (v instanceof TextView) {
setViewText((TextView) v, text);
} else if (v instanceof ImageView) {
setViewImage((ImageView) v, text);
} else {
throw new IllegalStateException(v.getClass().getName() + " is not a " +
" view that can be bounds by this SimpleCursorAdapter");
}
}
}
}
}
/**
* Returns the {@link ViewBinder} used to bind data to views.
*
* @return a ViewBinder or null if the binder does not exist
*
* @see #bindView(android.view.View, android.content.Context, android.database.Cursor)
* @see #setViewBinder(android.widget.SimpleCursorAdapter.ViewBinder)
*/
public ViewBinder getViewBinder() {
return mViewBinder;
}
/**
* Sets the binder used to bind data to views.
*
* @param viewBinder the binder used to bind data to views, can be null to
* remove the existing binder
*
* @see #bindView(android.view.View, android.content.Context, android.database.Cursor)
* @see #getViewBinder()
*/
public void setViewBinder(ViewBinder viewBinder) {
mViewBinder = viewBinder;
}
/**
* Called by bindView() to set the image for an ImageView but only if
* there is no existing ViewBinder or if the existing ViewBinder cannot
* handle binding to an ImageView.
*
* By default, the value will be treated as an image resource. If the
* value cannot be used as an image resource, the value is used as an
* image Uri.
*
* Intended to be overridden by Adapters that need to filter strings
* retrieved from the database.
*
* @param v ImageView to receive an image
* @param value the value retrieved from the cursor
*/
public void setViewImage(ImageView v, String value) {
try {
v.setImageResource(Integer.parseInt(value));
} catch (NumberFormatException nfe) {
v.setImageURI(Uri.parse(value));
}
}
/**
* Called by bindView() to set the text for a TextView but only if
* there is no existing ViewBinder or if the existing ViewBinder cannot
* handle binding to an TextView.
*
* Intended to be overridden by Adapters that need to filter strings
* retrieved from the database.
*
* @param v TextView to receive text
* @param text the text to be set for the TextView
*/
public void setViewText(TextView v, String text) {
v.setText(text);
}
/**
* Return the index of the column used to get a String representation
* of the Cursor.
*
* @return a valid index in the current Cursor or -1
*
* @see android.widget.CursorAdapter#convertToString(android.database.Cursor)
* @see #setStringConversionColumn(int)
* @see #setCursorToStringConverter(android.widget.SimpleCursorAdapter.CursorToStringConverter)
* @see #getCursorToStringConverter()
*/
public int getStringConversionColumn() {
return mStringConversionColumn;
}
/**
* Defines the index of the column in the Cursor used to get a String
* representation of that Cursor. The column is used to convert the
* Cursor to a String only when the current CursorToStringConverter
* is null.
*
* @param stringConversionColumn a valid index in the current Cursor or -1 to use the default
* conversion mechanism
*
* @see android.widget.CursorAdapter#convertToString(android.database.Cursor)
* @see #getStringConversionColumn()
* @see #setCursorToStringConverter(android.widget.SimpleCursorAdapter.CursorToStringConverter)
* @see #getCursorToStringConverter()
*/
public void setStringConversionColumn(int stringConversionColumn) {
mStringConversionColumn = stringConversionColumn;
}
/**
* Returns the converter used to convert the filtering Cursor
* into a String.
*
* @return null if the converter does not exist or an instance of
* {@link android.widget.SimpleCursorAdapter.CursorToStringConverter}
*
* @see #setCursorToStringConverter(android.widget.SimpleCursorAdapter.CursorToStringConverter)
* @see #getStringConversionColumn()
* @see #setStringConversionColumn(int)
* @see android.widget.CursorAdapter#convertToString(android.database.Cursor)
*/
public CursorToStringConverter getCursorToStringConverter() {
return mCursorToStringConverter;
}
/**
* Sets the converter used to convert the filtering Cursor
* into a String.
*
* @param cursorToStringConverter the Cursor to String converter, or
* null to remove the converter
*
* @see #setCursorToStringConverter(android.widget.SimpleCursorAdapter.CursorToStringConverter)
* @see #getStringConversionColumn()
* @see #setStringConversionColumn(int)
* @see android.widget.CursorAdapter#convertToString(android.database.Cursor)
*/
public void setCursorToStringConverter(CursorToStringConverter cursorToStringConverter) {
mCursorToStringConverter = cursorToStringConverter;
}
/**
* Returns a CharSequence representation of the specified Cursor as defined
* by the current CursorToStringConverter. If no CursorToStringConverter
* has been set, the String conversion column is used instead. If the
* conversion column is -1, the returned String is empty if the cursor
* is null or Cursor.toString().
*
* @param cursor the Cursor to convert to a CharSequence
*
* @return a non-null CharSequence representing the cursor
*/
@Override
public CharSequence convertToString(Cursor cursor) {
if (mCursorToStringConverter != null) {
return mCursorToStringConverter.convertToString(cursor);
} else if (mStringConversionColumn > -1) {
return cursor.getString(mStringConversionColumn);
}
return super.convertToString(cursor);
}
/**
* Create a map from an array of strings to an array of column-id integers in mCursor.
* If mCursor is null, the array will be discarded.
*
* @param from the Strings naming the columns of interest
*/
private void findColumns(String[] from) {
if (mCursor != null) {
int i;
int count = from.length;
if (mFrom == null || mFrom.length != count) {
mFrom = new int[count];
}
for (i = 0; i < count; i++) {
mFrom[i] = mCursor.getColumnIndexOrThrow(from[i]);
}
} else {
mFrom = null;
}
}
@Override
public Cursor swapCursor(Cursor c) {
// super.swapCursor() will notify observers before we have
// a valid mapping, make sure we have a mapping before this
// happens
if (mFrom == null) {
findColumns(mOriginalFrom);
}
Cursor res = super.swapCursor(c);
// rescan columns in case cursor layout is different
findColumns(mOriginalFrom);
return res;
}
/**
* Change the cursor and change the column-to-view mappings at the same time.
*
* @param c The database cursor. Can be null if the cursor is not available yet.
* @param from A list of column names representing the data to bind to the UI. Can be null
* if the cursor is not available yet.
* @param to The views that should display column in the "from" parameter.
* These should all be TextViews. The first N views in this list
* are given the values of the first N columns in the from
* parameter. Can be null if the cursor is not available yet.
*/
public void changeCursorAndColumns(Cursor c, String[] from, int[] to) {
mOriginalFrom = from;
mTo = to;
// super.changeCursor() will notify observers before we have
// a valid mapping, make sure we have a mapping before this
// happens
if (mFrom == null) {
findColumns(mOriginalFrom);
}
super.changeCursor(c);
findColumns(mOriginalFrom);
}
/**
* This class can be used by external clients of SimpleCursorAdapter
* to bind values fom the Cursor to views.
*
* You should use this class to bind values from the Cursor to views
* that are not directly supported by SimpleCursorAdapter or to
* change the way binding occurs for views supported by
* SimpleCursorAdapter.
*
* @see SimpleCursorAdapter#bindView(android.view.View, android.content.Context, android.database.Cursor)
* @see SimpleCursorAdapter#setViewImage(ImageView, String)
* @see SimpleCursorAdapter#setViewText(TextView, String)
*/
public static interface ViewBinder {
/**
* Binds the Cursor column defined by the specified index to the specified view.
*
* When binding is handled by this ViewBinder, this method must return true.
* If this method returns false, SimpleCursorAdapter will attempts to handle
* the binding on its own.
*
* @param view the view to bind the data to
* @param cursor the cursor to get the data from
* @param columnIndex the column at which the data can be found in the cursor
*
* @return true if the data was bound to the view, false otherwise
*/
boolean setViewValue(View view, Cursor cursor, int columnIndex);
}
/**
* This class can be used by external clients of SimpleCursorAdapter
* to define how the Cursor should be converted to a String.
*
* @see android.widget.CursorAdapter#convertToString(android.database.Cursor)
*/
public static interface CursorToStringConverter {
/**
* Returns a CharSequence representing the specified Cursor.
*
* @param cursor the cursor for which a CharSequence representation
* is requested
*
* @return a non-null CharSequence representing the cursor
*/
CharSequence convertToString(Cursor cursor);
}
}
沒有留言:
張貼留言
你好,我是小書,如果文章內容有錯誤,或是看到有建議以及任何感想時,歡迎提出分享,我們一起學習一起努力。