注:本文翻譯自Google官方的Android Developers Training文檔,譯者技術(shù)一般,由于喜愛安卓而產(chǎn)生了翻譯的念頭,純屬個人興趣愛好。
原文鏈接: http://developer.android.com/training/contacts-provider/display-contact-badge.html
這節(jié)課將會向你展示如何添加一個 QuickContactBadge 到你的UI中,以及如何將數(shù)據(jù)和它捆綁起來。一個 QuickContactBadge 是一個顯示縮略圖的空間。雖然你可以使用 Bitmap 顯示任何縮略圖,但是你必須要將聯(lián)系人照片進行解碼。
縮略圖的作用類似于一個控制器:當(dāng)用戶點擊縮略圖時,
QuickContactBadge
會擴展成一個對話框,其中包含如下內(nèi)容:
一個放大的圖標(biāo)
一個和該聯(lián)系人關(guān)聯(lián)的大圖標(biāo),如果沒有的話,就用一個默認(rèn)的占位圖片代替。
應(yīng)用圖標(biāo)
每一個具體的聯(lián)系人信息旁會有一個應(yīng)用圖標(biāo),它說明該數(shù)據(jù)可被此內(nèi)置應(yīng)用處理。例如,如果聯(lián)系人的數(shù)據(jù)中有一個或多個email地址,那么就會出現(xiàn)一個email的圖標(biāo)。當(dāng)用戶點擊這個圖標(biāo),聯(lián)系人的所有email地址會顯示出來,之后用戶如果點擊了某一個email地址,會打開電子郵件應(yīng)用,其中的收件人地址就是所選中的email地址。
QuickContactBadge 提供了一個指向聯(lián)系人詳細(xì)信息的即時訪問,以及一個和聯(lián)系人溝通的快速渠道。用戶不需要查詢聯(lián)系人列表,尋找并拷貝信息,之后再把它粘貼到其它的應(yīng)用界面中去。取而代之的,它們只需要在 QuickContactBadge 上進行點擊,選擇他們想要使用的溝通方式,并直接通過相關(guān)的應(yīng)用發(fā)送消息即可。
一). 添加一個QuickContactBadge視圖
要添加一個 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
>
二). 檢索提供器的數(shù)據(jù)
要在 QuickContactBadge 中顯示一個聯(lián)系人,你需要一個聯(lián)系人的內(nèi)容URI還有縮略圖的 Bitmap 對象。你從Contacts Provider搜索的列數(shù)據(jù)用來創(chuàng)建內(nèi)容URI和 Bitmap 對象。指定這些列左右你在 Cursor 中用來加載數(shù)據(jù)的投影的一部分。
對Android 3.0(API版本11)及之后的版本,在你的投影中包含下面幾列:
對Android 2.3.3(API版本10)及之前的版本,在你的投影中包含下面幾列:
我們假設(shè)在這節(jié)課之前,你已經(jīng)加載了一個 Cursor ,它包含了上面的這些列,還有一些你已經(jīng)選擇了的列。要學(xué)習(xí)如何使用 Cursor 檢索這些列數(shù)據(jù),可以參閱: Retrieving a List of Contacts (博客鏈接: http://www.cnblogs.com/jdneo/p/3674830.html )
三). 設(shè)置內(nèi)容URI和縮略圖
一旦你有了必要的列,你就可以將數(shù)據(jù)綁定到 QuickContactBadge 上。
設(shè)置內(nèi)容URI
要為聯(lián)系人的內(nèi)容URI,調(diào)用 getLookupUri(id,lookupKey) 來獲取一個 CONTENT_LOOKUP_URI ,然后調(diào)用 assignContactUri() 來設(shè)置聯(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);
當(dāng)用戶點擊了 QuickContactBadge 圖標(biāo)后,聯(lián)系人的詳細(xì)信息會自動顯示在對話框中。
設(shè)置照片縮略圖
為 QuickContactBadge 設(shè)置聯(lián)系人的URI并不會自動的加載他的照片。要加載照片,需要從聯(lián)系人的 Cursor 行中獲取照片的URI,使用它來打開包含有壓縮后的照片縮略圖文件,并將該文件讀入一個 Bitmap 對象。
Note:
PHOTO_THUMBNAIL_URI 列在Android 3.0之前的版本中是沒有的。對于那些較早的版本,你必須從 Contacts.Photo 自表中獲取URI。
首先,為訪問包含有 Contacts._ID 和 Contacts.LOOKUP_KEY 列的 Cursor 設(shè)置變量,如下所示:
//
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)系人的照片數(shù)據(jù),以及縮略圖的目標(biāo)大小,并將照片以一個適當(dāng)尺寸的 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 對象,將結(jié)果用來設(shè)置你的 QuickContactBadge 中的聯(lián)系人縮略圖:
...
/*
* 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到ListView中
一個 QuickContactBadge 是一個ListView的非常有用的控件,它會顯示聯(lián)系人的列表。使用 QuickContactBadge 為每一個聯(lián)系人顯示他的縮略圖;當(dāng)用戶點擊縮略圖后, QuickContactBadge 對話框會出現(xiàn)。
添加QuickContactBadge元素
首先,添加一個 QuickContactBadge 視圖元素到你的列表項布局中。例如,如果你想要顯示一個 QuickContactBadge 還有你檢索的每個聯(lián)系人的名字,將下列XML放置到一個布局文件中:
<
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
要將一個
CursorAdapter
綁定到一個包含有
QuickContactBadge
的
ListView
上,自定義一個自定義的適配器,它繼承自
CursorAdapter
。這一方法允許你在將
Cursor
綁定到
QuickContactBadge
之前,可以在
Cursor
內(nèi)處理數(shù)據(jù)。同時這個方法還允許你將多個
Cursor
列綁定到
QuickContactBadge
上。這些方法對于一個傳統(tǒng)的
CursorAdapter
而言是不可能做到的。
對于 CursorAdapter 的子類,你必須覆寫下列方法:
填充一個新的 View 對象來顯示列表項布局。在該方法的覆寫版本中,保存布局中子 View 對象的句柄,包括子 QuickContactBadge 。通過使用這一方法,你可以避免每次你填充一個新的布局時去獲取子 View 對象的句柄。
你必須要覆寫這一方法,這樣你才能獲取每個自 View 對象的句柄。這一方法允許你在 CursorAdapter.bindView() 方法中控制他們的捆綁關(guān)系。
將數(shù)據(jù)從當(dāng)前的 Cursor 行移動到列表項布局中子 View 對象里。你必須覆寫這一方法這樣你就能同時將聯(lián)系人URI和縮略圖捆綁到 QuickContactBadge 上。而默認(rèn)的實現(xiàn)值允許一列數(shù)據(jù)和一個 View 間一對一的對應(yīng)關(guān)系。
下面的代碼片段包含了自定義子類 CursorAdapter 的一個例子:
定義自定義列表適配器
定義 CursorAdapter 的子類,包括它的構(gòu)造函數(shù),覆寫 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è)置變量
在你的代碼中,設(shè)置變量,包括一個 Cursor 投影,它包含了必要的那些列。
Note:
下面的代碼片段使用了 loadContactPhotoThumbnail() 方法,這在之前的章節(jié)中該方法已經(jīng)詳細(xì)敘述過了。
例如:
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
;
...
設(shè)置ListView
在 Fragment.onCreate() 中,實例化自定義的 cursor適配器,并獲得一個 ListView 的句柄:
@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);
...
}
...
當(dāng)你獲取了一個包含有聯(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);
}
當(dāng)你通過一個
CursorAdapter
(或它的子類)將一個
Cursor
綁定到
ListView
上,并且你使用
CursorLoader
加載
Cursor
,一定要記得在
onLoaderReset()
的實現(xiàn)中清楚
Cursor
的引用,例如:
@Override
public
void
onLoaderReset(Loader<Cursor>
loader) {
//
Removes remaining reference to the previous Cursor
mContactsAdapter.swapCursor(
null
);
}
【Android Developers Training】 101. 顯示快速聯(lián)系人掛件(Quick Contact Badge)
更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主
微信掃碼或搜索:z360901061
微信掃一掃加我為好友
QQ號聯(lián)系: 360901061
您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對您有幫助就好】元

