W3Cschool
恭喜您成為首批注冊用戶
獲得88經(jīng)驗值獎勵
編寫:spencer198711 - 原文:http://developer.android.com/training/contacts-provider/display-contact-badge.html
這一課展示了如何在我們的應(yīng)用界面上添加一個QuickContactBadge,以及如何為它綁定數(shù)據(jù)。 QuickContactBadge是一個在初始情況下顯示聯(lián)系人縮略圖頭像的widget。盡管我們可以使用任何Bitmap作為縮略圖頭像,但是我們通常會使用從聯(lián)系人照片縮略圖中解碼出來的Bitmap。
這個小的圖片是一個控件,當用戶點擊它時,QuickContactBadge會展開一個包含以下內(nèi)容的對話框:
一個大的聯(lián)系人頭像
與這個聯(lián)系人關(guān)聯(lián)的大的頭像,如果此人沒有設(shè)置頭像,則顯示預(yù)留的圖案。
應(yīng)用程序圖標
根據(jù)聯(lián)系人詳情數(shù)據(jù),顯示每一個能夠被手機中的應(yīng)用所處理的數(shù)據(jù)的圖標。例如,如果聯(lián)系人的數(shù)據(jù)包含一個或多個email地址,就會顯示email應(yīng)用的圖標。當用戶點擊這個圖標的時候,這個聯(lián)系人所有的email地址都會顯示出來。當用戶點擊其中一個email地址時,email應(yīng)用將會顯示一個界面,讓用戶為選中的地址撰寫郵件。
QuickContactBadge視圖提供了對聯(lián)系人數(shù)據(jù)的即時訪問,是一種與聯(lián)系人溝通的快捷方式。用戶不用查詢一個聯(lián)系人,查找并復(fù)制信息,然后把信息粘貼到合適的應(yīng)用中。他們可以點擊QuickContactBadge,選擇他們想要的溝通方式,然后直接把信息發(fā)送給合適的應(yīng)用中。
為了添加一個QuickContactBadge視圖,需要在布局文件中插入一個QuickContactBadge。例如:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
...
<QuickContactBadge
android:id=@+id/quickbadge
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:scaleType="centerCrop"/>
...
</RelativeLayout>
為了能在QuickContactBadge中顯示聯(lián)系人,我們需要這個聯(lián)系人的內(nèi)容URI和顯示頭像的Bitmap。我們可以從在Contacts Provider中獲取到的數(shù)據(jù)列中生成這兩個數(shù)據(jù)。需要指定這些列作為查詢映射去把數(shù)據(jù)加載到Cursor中。
對于Android 3.0(API版本為11)以及以后的版本,需要在查詢映射中添加以下列:
對于Android 2.3.3(API版本為10)以及之前的版本,則使用以下列:
這一課的剩余部分假設(shè)你已經(jīng)獲取到了包含這些以及其他你可能選擇的數(shù)據(jù)列的Cursor對象。想要學(xué)習(xí)如何獲取這些列對象的Cursor,請參閱課程獲取聯(lián)系人列表。
一旦我們已經(jīng)擁有了所需的數(shù)據(jù)列,那么我們就可以為QuickContactBadge視圖綁定數(shù)據(jù)了。
為了設(shè)置聯(lián)系人URI,需要調(diào)用getLookupUri(id, lookupKey)去獲取CONTENT_LOOKUP_URI,然后調(diào)用assignContactUri())去為QuickContactBadge設(shè)置對應(yīng)的聯(lián)系人。例如:
// The Cursor that contains contact rows
Cursor mCursor;
// The index of the _ID column in the Cursor
int mIdColumn;
// The index of the LOOKUP_KEY column in the Cursor
int mLookupKeyColumn;
// A content URI for the desired contact
Uri mContactUri;
// A handle to the QuickContactBadge view
QuickContactBadge mBadge;
...
mBadge = (QuickContactBadge) findViewById(R.id.quickbadge);
/*
* Insert code here to move to the desired cursor row
*/
// Gets the _ID column index
mIdColumn = mCursor.getColumnIndex(Contacts._ID);
// Gets the LOOKUP_KEY index
mLookupKeyColumn = mCursor.getColumnIndex(Contacts.LOOKUP_KEY);
// Gets a content URI for the contact
mContactUri =
Contacts.getLookupUri(
mCursor.getLong(mIdColumn),
mCursor.getString(mLookupKeyColumn)
);
mBadge.assignContactUri(mContactUri);
當用戶點擊QuickContactBadge圖標的時候,這個聯(lián)系人的詳細信息將會自動展現(xiàn)在對話框中。
為QuickContactBadge設(shè)置聯(lián)系人URI并不會自動加載聯(lián)系人的縮略圖照片。為了加載聯(lián)系人照片,需要從聯(lián)系人的Cursor對象的一行數(shù)據(jù)中獲取照片的URI,使用這個URI去打開包含壓縮的縮略圖文件,并把這個文件讀到Bitmap對象中。
Note:PHOTO_THUMBNAIL_URI這一列在Android 3.0之前的版本是不存在的。對于這些版本,我們必須從Contacts.Photo表中獲取照片的URI。
首先,為包含Contacts._ID和Contacts.LOOKUP_KEY的Cursor數(shù)據(jù)列設(shè)置對應(yīng)的變量,這在之前已經(jīng)有描述:
// The column in which to find the thumbnail ID
int mThumbnailColumn;
/*
* The thumbnail URI, expressed as a String.
* Contacts Provider stores URIs as String values.
*/
String mThumbnailUri;
...
/*
* Gets the photo thumbnail column index if
* platform version >= Honeycomb
*/
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
mThumbnailColumn =
mCursor.getColumnIndex(Contacts.PHOTO_THUMBNAIL_URI);
// Otherwise, sets the thumbnail column to the _ID column
} else {
mThumbnailColumn = mIdColumn;
}
/*
* Assuming the current Cursor position is the contact you want,
* gets the thumbnail ID
*/
mThumbnailUri = mCursor.getString(mThumbnailColumn);
...
定義一個方法,使用與這個聯(lián)系人的照片有關(guān)的數(shù)據(jù)和目標視圖的尺寸作為參數(shù),返回一個尺寸合適的縮略圖Bitmap對象。下面先構(gòu)建一個指向這個縮略圖的URI:
/**
* Load a contact photo thumbnail and return it as a Bitmap,
* resizing the image to the provided image dimensions as needed.
* @param photoData photo ID Prior to Honeycomb, the contact's _ID value.
* For Honeycomb and later, the value of PHOTO_THUMBNAIL_URI.
* @return A thumbnail Bitmap, sized to the provided width and height.
* Returns null if the thumbnail is not found.
*/
private Bitmap loadContactPhotoThumbnail(String photoData) {
// Creates an asset file descriptor for the thumbnail file.
AssetFileDescriptor afd = null;
// try-catch block for file not found
try {
// Creates a holder for the URI.
Uri thumbUri;
// If Android 3.0 or later
if (Build.VERSION.SDK_INT
>=
Build.VERSION_CODES.HONEYCOMB) {
// Sets the URI from the incoming PHOTO_THUMBNAIL_URI
thumbUri = Uri.parse(photoData);
} else {
// Prior to Android 3.0, constructs a photo Uri using _ID
/*
* Creates a contact URI from the Contacts content URI
* incoming photoData (_ID)
*/
final Uri contactUri = Uri.withAppendedPath(
Contacts.CONTENT_URI, photoData);
/*
* Creates a photo URI by appending the content URI of
* Contacts.Photo.
*/
thumbUri =
Uri.withAppendedPath(
contactUri, Photo.CONTENT_DIRECTORY);
}
/*
* Retrieves an AssetFileDescriptor object for the thumbnail
* URI
* using ContentResolver.openAssetFileDescriptor
*/
afd = getActivity().getContentResolver().
openAssetFileDescriptor(thumbUri, "r");
/*
* Gets a file descriptor from the asset file descriptor.
* This object can be used across processes.
*/
FileDescriptor fileDescriptor = afd.getFileDescriptor();
// Decode the photo file and return the result as a Bitmap
// If the file descriptor is valid
if (fileDescriptor != null) {
// Decodes the bitmap
return BitmapFactory.decodeFileDescriptor(
fileDescriptor, null, null);
}
// If the file isn't found
} catch (FileNotFoundException e) {
/*
* Handle file not found errors
*/
}
// In all cases, close the asset file descriptor
} finally {
if (afd != null) {
try {
afd.close();
} catch (IOException e) {}
}
}
return null;
}
在代碼中調(diào)用loadContactPhotoThumbnail()去獲取縮略圖Bitmap對象,使用獲取的Bitmap對象去設(shè)置QuickContactBadge頭像縮略圖。
...
/*
* Decodes the thumbnail file to a Bitmap.
*/
Bitmap mThumbnail =
loadContactPhotoThumbnail(mThumbnailUri);
/*
* Sets the image in the QuickContactBadge
* QuickContactBadge inherits from ImageView, so
*/
mBadge.setImageBitmap(mThumbnail);
QuickContactBadge對于一個展示聯(lián)系人列表的ListView來說是一個非常有用的添加功能。使用QuickContactBadge去為每一個聯(lián)系人顯示一個縮略圖,當用戶點擊這個縮略圖時,QuickContactBadge對話框?qū)@示。
首先,在列表項布局文件中添加QuickContactBadge視圖元素。例如,如果我們想為獲取到的每一個聯(lián)系人顯示QuickContactBadge和名字,把以下的XML內(nèi)容放到對應(yīng)的布局文件中:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<QuickContactBadge
android:id="@+id/quickcontact"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:scaleType="centerCrop"/>
<TextView android:id="@+id/displayname"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_toRightOf="@+id/quickcontact"
android:gravity="center_vertical"
android:layout_alignParentRight="true"
android:layout_alignParentTop="true"/>
</RelativeLayout>
在以下的章節(jié)中,這個文件被稱為contact_item_layout.xml
。
定義一個繼承自CursorAdapter的adapter來將CursorAdapter綁定到一個包含QuickContactBadge的ListView中。這種方式允許我們在綁定數(shù)據(jù)到QuickContactBadge之前對Cursor中的數(shù)據(jù)進行處理。同時也能將多個Cursor中的列綁定到QuickContactBadge。而使用普通的CursorAdapter是不能完成這些操作的。
我們定義的CursorAdapter的子類必須重寫以下方法:
填充一個View對象去持有列表項布局。在重寫這個方法的過程中,需要保存這個布局的子View的handles,包括QuickContactBadge的handles。通過采用這種方法,避免了每次在填充新的布局時都去獲取子View的handles。
我們必須重寫這個方法以便能夠獲取每個子View對象的handles。這種方法允許我們控制這些子View對象在CursorAdapter.bindView()方法中的綁定。
將數(shù)據(jù)從當前Cursor行綁定到列表項布局的子View對象中。必須重寫這個方法以便能夠?qū)⒙?lián)系人的URI和縮略圖信息綁定到QuickContactBadge。這個方法的默認實現(xiàn)僅僅允許在數(shù)據(jù)列和View之間的一對一映射。
以下的代碼片段是一個包含了自定義CursorAdapter子類的例子。
定義CursorAdapter的子類包括編寫這個類的構(gòu)造方法,以及重寫newView()和bindView():
private class ContactsAdapter extends CursorAdapter {
private LayoutInflater mInflater;
...
public ContactsAdapter(Context context) {
super(context, null, 0);
/*
* Gets an inflater that can instantiate
* the ListView layout from the file.
*/
mInflater = LayoutInflater.from(context);
...
}
...
/**
* Defines a class that hold resource IDs of each item layout
* row to prevent having to look them up each time data is
* bound to a row.
*/
private class ViewHolder {
TextView displayname;
QuickContactBadge quickcontact;
}
..
@Override
public View newView(
Context context,
Cursor cursor,
ViewGroup viewGroup) {
/* Inflates the item layout. Stores resource IDs in a
* in a ViewHolder class to prevent having to look
* them up each time bindView() is called.
*/
final View itemView =
mInflater.inflate(
R.layout.contact_list_layout,
viewGroup,
false
);
final ViewHolder holder = new ViewHolder();
holder.displayname =
(TextView) view.findViewById(R.id.displayname);
holder.quickcontact =
(QuickContactBadge)
view.findViewById(R.id.quickcontact);
view.setTag(holder);
return view;
}
...
@Override
public void bindView(
View view,
Context context,
Cursor cursor) {
final ViewHolder holder = (ViewHolder) view.getTag();
final String photoData =
cursor.getString(mPhotoDataIndex);
final String displayName =
cursor.getString(mDisplayNameIndex);
...
// Sets the display name in the layout
holder.displayname = cursor.getString(mDisplayNameIndex);
...
/*
* Generates a contact URI for the QuickContactBadge.
*/
final Uri contactUri = Contacts.getLookupUri(
cursor.getLong(mIdIndex),
cursor.getString(mLookupKeyIndex));
holder.quickcontact.assignContactUri(contactUri);
String photoData = cursor.getString(mPhotoDataIndex);
/*
* Decodes the thumbnail file to a Bitmap.
* The method loadContactPhotoThumbnail() is defined
* in the section "Set the Contact URI and Thumbnail"
*/
Bitmap thumbnailBitmap =
loadContactPhotoThumbnail(photoData);
/*
* Sets the image in the QuickContactBadge
* QuickContactBadge inherits from ImageView
*/
holder.quickcontact.setImageBitmap(thumbnailBitmap);
}
在代碼中,設(shè)置相關(guān)變量,添加一個包括必須數(shù)據(jù)列的Cursor。
Note:以下的代碼片段使用了方法
loadContactPhotoThumbnail()
,這個方法是在設(shè)置聯(lián)系人URI和縮略圖那一節(jié)中定義的。
例如:
public class ContactsFragment extends Fragment implements
LoaderManager.LoaderCallbacks<Cursor> {
...
// Defines a ListView
private ListView mListView;
// Defines a ContactsAdapter
private ContactsAdapter mAdapter;
...
// Defines a Cursor to contain the retrieved data
private Cursor mCursor;
/*
* Defines a projection based on platform version. This ensures
* that you retrieve the correct columns.
*/
private static final String[] PROJECTION =
{
Contacts._ID,
Contacts.LOOKUP_KEY,
(Build.VERSION.SDK_INT >=
Build.VERSION_CODES.HONEYCOMB) ?
Contacts.DISPLAY_NAME_PRIMARY :
Contacts.DISPLAY_NAME
(Build.VERSION.SDK_INT >=
Build.VERSION_CODES.HONEYCOMB) ?
Contacts.PHOTO_THUMBNAIL_ID :
/*
* Although it's not necessary to include the
* column twice, this keeps the number of
* columns the same regardless of version
*/
Contacts_ID
...
};
/*
* As a shortcut, defines constants for the
* column indexes in the Cursor. The index is
* 0-based and always matches the column order
* in the projection.
*/
// Column index of the _ID column
private int mIdIndex = 0;
// Column index of the LOOKUP_KEY column
private int mLookupKeyIndex = 1;
// Column index of the display name column
private int mDisplayNameIndex = 3;
/*
* Column index of the photo data column.
* It's PHOTO_THUMBNAIL_URI for Honeycomb and later,
* and _ID for previous versions.
*/
private int mPhotoDataIndex =
Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB ?
3 :
0;
...
在Fragment.onCreate())方法中,實例化自定義的adapter對象,獲得一個ListView的handle。
@Override
public void onCreate(Bundle savedInstanceState) {
...
/*
* Instantiates the subclass of
* CursorAdapter
*/
ContactsAdapter mContactsAdapter =
new ContactsAdapter(getActivity());
/*
* Gets a handle to the ListView in the file
* contact_list_layout.xml
*/
mListView = (ListView) findViewById(R.layout.contact_list_layout);
...
}
...
在onActivityCreated())方法中,將ContactsAdapter綁定到ListView。
@Override
public void onActivityCreated(Bundle savedInstanceState) {
...
// Sets up the adapter for the ListView
mListView.setAdapter(mAdapter);
...
}
...
當獲取到一個包含聯(lián)系人數(shù)據(jù)的Cursor時(通常在onLoadFinished()的時候),調(diào)用swapCursor()把Cursor中的數(shù)據(jù)綁定到ListView。這將會為聯(lián)系人列表中的每一項都顯示一個QuickContactBadge。
public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) {
// When the loader has completed, swap the cursor into the adapter.
mContactsAdapter.swapCursor(cursor);
}
當我們使用CursorAdapter或其子類中將Cursor中的數(shù)據(jù)綁定到ListView,并且使用了CursorLoader去加載Cursor數(shù)據(jù)時,記得要在onLoaderReset()方法的實現(xiàn)中清理對Cursor對象的引用。例如:
@Override
public void onLoaderReset(Loader<Cursor> loader) {
// Removes remaining reference to the previous Cursor
mContactsAdapter.swapCursor(null);
}
Copyright©2021 w3cschool編程獅|閩ICP備15016281號-3|閩公網(wǎng)安備35020302033924號
違法和不良信息舉報電話:173-0602-2364|舉報郵箱:jubao@eeedong.com
掃描二維碼
下載編程獅App
編程獅公眾號
聯(lián)系方式:
更多建議: