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