注:本文翻译自Google官方的Android Developers Training文档,译者技术一般,由于喜爱安卓而产生了翻译的念头,纯属个人兴趣爱好。

原文链接:http://developer.android.com/training/contacts-provider/display-contact-badge.html


这节课将会向你展示如何添加一个QuickContactBadge到你的UI中,以及如何将数据和它捆绑起来。一个QuickContactBadge是一个显示缩略图的空间。虽然你可以使用Bitmap显示任何缩略图,但是你必须要将联系人照片进行解码。

缩略图的作用类似于一个控制器:当用户点击缩略图时,QuickContactBadge会扩展成一个对话框,其中包含如下内容:

一个放大的图标

一个和该联系人关联的大图标,如果没有的话,就用一个默认的占位图片代替。

应用图标

每一个具体的联系人信息旁会有一个应用图标,它说明该数据可被此内置应用处理。例如,如果联系人的数据中有一个或多个email地址,那么就会出现一个email的图标。当用户点击这个图标,联系人的所有email地址会显示出来,之后用户如果点击了某一个email地址,会打开电子邮件应用,其中的收件人地址就是所选中的email地址。

QuickContactBadge提供了一个指向联系人详细信息的即时访问,以及一个和联系人沟通的快速渠道。用户不需要查询联系人列表,寻找并拷贝信息,之后再把它粘贴到其它的应用界面中去。取而代之的,它们只需要在QuickContactBadge上进行点击,选择他们想要使用的沟通方式,并直接通过相关的应用发送消息即可。


一). 添加一个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>

二). 检索提供器的数据

要在QuickContactBadge中显示一个联系人,你需要一个联系人的内容URI还有缩略图的Bitmap对象。你从Contacts Provider搜索的列数据用来创建内容URI和Bitmap对象。指定这些列左右你在Cursor中用来加载数据的投影的一部分。

对Android 3.0(API版本11)及之后的版本,在你的投影中包含下面几列:

对Android 2.3.3(API版本10)及之前的版本,在你的投影中包含下面几列:

我们假设在这节课之前,你已经加载了一个Cursor,它包含了上面的这些列,还有一些你已经选择了的列。要学习如何使用Cursor检索这些列数据,可以参阅:Retrieving a List of Contacts(博客链接:http://www.cnblogs.com/jdneo/p/3674830.html


三). 设置内容URI和缩略图

一旦你有了必要的列,你就可以将数据绑定到QuickContactBadge上。

设置内容URI

要为联系人的内容URI,调用getLookupUri(id,lookupKey)来获取一个CONTENT_LOOKUP_URI,然后调用assignContactUri()来设置联系人。例如:

    // 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图标后,联系人的详细信息会自动显示在对话框中。

设置照片缩略图

QuickContactBadge设置联系人的URI并不会自动的加载他的照片。要加载照片,需要从联系人的Cursor行中获取照片的URI,使用它来打开包含有压缩后的照片缩略图文件,并将该文件读入一个Bitmap对象。

Note:

PHOTO_THUMBNAIL_URI列在Android 3.0之前的版本中是没有的。对于那些较早的版本,你必须从Contacts.Photo自表中获取URI。

首先,为访问包含有Contacts._IDContacts.LOOKUP_KEY列的Cursor设置变量,如下所示:

    // 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);
...

定义一个方法,它获取联系人的照片数据,以及缩略图的目标大小,并将照片以一个适当尺寸的Bitmap形式返回。我们首先从构造一个指向该缩略图的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;
}

在你的代码中调用loadContactPhotoThumbnail()来获取缩略图的Bitmap对象,将结果用来设置你的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到ListView中

一个QuickContactBadge是一个ListView的非常有用的控件,它会显示联系人的列表。使用QuickContactBadge为每一个联系人显示他的缩略图;当用户点击缩略图后,QuickContactBadge对话框会出现。

添加QuickContactBadge元素

首先,添加一个QuickContactBadge视图元素到你的列表项布局中。例如,如果你想要显示一个QuickContactBadge还有你检索的每个联系人的名字,将下列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>

在下面的章节中,这一文件我们称它为:contact_item_layout.xml

配置一个自定义CursorAdapter

要将一个CursorAdapter绑定到一个包含有QuickContactBadgeListView上,自定义一个自定义的适配器,它继承自CursorAdapter。这一方法允许你在将Cursor绑定到QuickContactBadge之前,可以在Cursor内处理数据。同时这个方法还允许你将多个Cursor列绑定到QuickContactBadge上。这些方法对于一个传统的CursorAdapter而言是不可能做到的。

对于CursorAdapter的子类,你必须覆写下列方法:

CursorAdapter.newView()

填充一个新的View对象来显示列表项布局。在该方法的覆写版本中,保存布局中子View对象的句柄,包括子QuickContactBadge。通过使用这一方法,你可以避免每次你填充一个新的布局时去获取子View对象的句柄。

你必须要覆写这一方法,这样你才能获取每个自View对象的句柄。这一方法允许你在CursorAdapter.bindView()方法中控制他们的捆绑关系。

CursorAdapter.bindView()

将数据从当前的Cursor行移动到列表项布局中子View对象里。你必须覆写这一方法这样你就能同时将联系人URI和缩略图捆绑到QuickContactBadge上。而默认的实现值允许一列数据和一个View间一对一的对应关系。

下面的代码片段包含了自定义子类CursorAdapter的一个例子:

定义自定义列表适配器

定义CursorAdapter的子类,包括它的构造函数,覆写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);
}

设置变量

在你的代码中,设置变量,包括一个Cursor投影,它包含了必要的那些列。

Note:

下面的代码片段使用了loadContactPhotoThumbnail()方法,这在之前的章节中该方法已经详细叙述过了。

例如:

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;
...

设置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()中,将ContactsAdapterListView绑定起来:

    @Override
public void onActivityCreated(Bundle savedInstanceState) {
...
// Sets up the adapter for the ListView
mListView.setAdapter(mAdapter);
...
}
...

当你获取了一个包含有联系人数据的Cursor,通常是在onLoadFinished(),调用swapCursor()Cursor数据移动到ListView。这会为联系人列表中的每一个条目显示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绑定到ListView上,并且你使用CursorLoader加载Cursor,一定要记得在onLoaderReset()的实现中清楚Cursor的引用,例如:

    @Override
public void onLoaderReset(Loader<Cursor> loader) {
// Removes remaining reference to the previous Cursor
mContactsAdapter.swapCursor(null);
}

【Android Developers Training】 101. 显示快速联系人挂件(Quick Contact Badge)的更多相关文章

  1. 【Android Developers Training】 99. 获取联系人详细信息

    注:本文翻译自Google官方的Android Developers Training文档,译者技术一般,由于喜爱安卓而产生了翻译的念头,纯属个人兴趣爱好. 原文链接:http://developer ...

  2. 【Android Developers Training】 98. 获取联系人列表

    注:本文翻译自Google官方的Android Developers Training文档,译者技术一般,由于喜爱安卓而产生了翻译的念头,纯属个人兴趣爱好. 原文链接:http://developer ...

  3. 【Android Developers Training】 97. 序言:访问通讯录数据

    注:本文翻译自Google官方的Android Developers Training文档,译者技术一般,由于喜爱安卓而产生了翻译的念头,纯属个人兴趣爱好. 原文链接:http://developer ...

  4. 【Android Developers Training】 100. 使用Intent修改联系人数据

    注:本文翻译自Google官方的Android Developers Training文档,译者技术一般,由于喜爱安卓而产生了翻译的念头,纯属个人兴趣爱好. 原文链接:http://developer ...

  5. 【Android Developers Training】 105. 显示一个位置地址

    注:本文翻译自Google官方的Android Developers Training文档,译者技术一般,由于喜爱安卓而产生了翻译的念头,纯属个人兴趣爱好. 原文链接:http://developer ...

  6. 【Android Developers Training】 71. 显示翻牌动画

    注:本文翻译自Google官方的Android Developers Training文档,译者技术一般,由于喜爱安卓而产生了翻译的念头,纯属个人兴趣爱好. 原文链接:http://developer ...

  7. 【Android Developers Training】 60. 在你的UI中显示位图

    注:本文翻译自Google官方的Android Developers Training文档,译者技术一般,由于喜爱安卓而产生了翻译的念头,纯属个人兴趣爱好. 原文链接:http://developer ...

  8. 【Android Developers Training】 55. 序言:高效显示位图

    注:本文翻译自Google官方的Android Developers Training文档,译者技术一般,由于喜爱安卓而产生了翻译的念头,纯属个人兴趣爱好. 原文链接:http://developer ...

  9. 【Android Developers Training】 108. 使用模拟定位进行测试

    注:本文翻译自Google官方的Android Developers Training文档,译者技术一般,由于喜爱安卓而产生了翻译的念头,纯属个人兴趣爱好. 原文链接:http://developer ...

随机推荐

  1. yaf学习之——yaf安装

    yaf的github源码地址 https://github.com/laruence/yaf 第一步: 下载dll扩展: http://pecl.php.net/package/yaf/2.3.5/w ...

  2. 【设计模式】之开闭原则(OCP)

    开闭原则是面向对象设计的一个重要原则,其定义如下: 开闭原则(Open-Closed Principle, OCP):一个软件实体应当对扩展开放,对修改关闭.即软件实体应尽量在不修改原有代码的情况下进 ...

  3. android组团开发站立会议第三周第一次会议

    会议时间:组队开发第三周  星期一   开始时间晚上9:30-10:00 会议地点:学一食堂 二楼 到会人员:李志岩  王亚蕊 安帅 薛禄坤 张新宇 孙存良 会议概要:              1. ...

  4. (HTTPS)-tomcat 实现 https 登录,去掉端口号

    最近项目组要给日本客户做个产品,升级服务器交由我来升级.为了测试用,想要在自己电脑上搭个服务器. 服务器需要由https登录,并且不显示端口号. 费了些劲儿,看了n多帖子,好不容易弄好了.趁在没忘记之 ...

  5. R语言进行文件夹操作示例(转)

    rm(list=ls())path = 'J:/lab/EX29 --在R语言中进行文件(夹)操作'setwd(path)cat("file A\n", file="A& ...

  6. centos7下,解决Apache错误日志文件过大问题

    1,日志文件太大问题   第一步:停止Apache服务的所有进程,删除 /var/log/httpd目录下的 error.log.access.log文件 第二步:打开 /etc/httpd/conf ...

  7. IT培训行业揭秘(六)

    2017年全国的IT职业培训机构的招生数量相比于去年同期都出现了大规模的下滑,虽然目前大学生毕业之后参加培训班的人数依然没有变化,但是目前中小培训机构像雨后春笋般的纷纷建立,他们纷纷抢占市场,为了招生 ...

  8. C#操作CAD-初始化、引用dll

    操作cad等方式有很多,比如C,C++,vb.lisp(效率最高,但是语言结构性太差)和C#,因为我等个人习惯和方便等原因,在此讲解一下用C#操作流程,后续会更新操作图层.扩展数据.绘图等操作步骤.当 ...

  9. MySQL开放远程登录

    在服务器上部署MYSQL每次观看MYSQL记录或者修改的时候都需要登录服务器,又烦又占资源.所以使用另一种方法:对外开放接口. 注:如果某些服务器开启防火墙屏蔽了某些接口就有可能导致远程用户无法登录M ...

  10. Java中设计模式之单例设计模式-1

    单例作用 1 节省内存 2 可以避免多种状态导致状态冲突 单例的创建步骤 1 私有化构造方法 2 私有化声明的属性 3 getInstance 4 方法需要静态 单例分类 1.懒汉式 2.饿汉式 两种 ...