快速联系Android,显示快速联系标志  |  Android 开发者  |  Android Developers

本课介绍了如何将

这张缩略图充当控件;当用户点击这张图像时,

大图像

大图像与相应的联系人相关;如果没有可用图像,则为占位符图像。应用图标

可由内置应用处理的每条详细数据对应的应用图标。例如,如果联系人的详细信息中包含一个或多个电子邮件地址,则会出现电子邮件图标。当用户点击该图标时,会看到该联系人的所有电子邮件地址。当用户点击其中一个地址时,对应的电子邮件应用会显示一个屏幕,供用户撰写要发送到所选电子邮件地址的邮件。

通过

添加 QuickContactBadge 视图

如需添加 元素。例如:

android:layout_width="match_parent"

android:layout_height="match_parent">

...

android:id=@+id/quickbadge

android:layout_height="wrap_content"

android:layout_width="wrap_content"

android:scaleType="centerCrop"/>

...

检索提供程序数据

如需在

对于 Android 3.0(API 级别 11)及更高版本,在映射中添加以下列:

对于 Android 2.3.3(API 级别 10)及更低版本,使用以下列:

本课的其余部分假定您已加载一个 检索联系人列表课程。

设置联系人 URI 和缩略图

添加了必要的列之后,您可以将数据绑定到

设置联系人 URI

Kotlin

// The Cursor that contains contact rows

var mCursor: Cursor? = null

// The index of the _ID column in the Cursor

var idColumn: Int = 0

// The index of the LOOKUP_KEY column in the Cursor

var lookupKeyColumn: Int = 0

// A content URI for the desired contact

var contactUri: Uri? = null

// A handle to the QuickContactBadge view

lateinit var mBadge: QuickContactBadge

...

mBadge = findViewById(R.id.quickbadge)

mCursor?.let { cursor ->

/*

* Insert code here to move to the desired cursor row

*/

// Gets the _ID column index

idColumn = cursor.getColumnIndex(ContactsContract.Contacts._ID)

// Gets the LOOKUP_KEY index

lookupKeyColumn = cursor.getColumnIndex(ContactsContract.Contacts.LOOKUP_KEY)

// Gets a content URI for the contact

contactUri = ContactsContract.Contacts.getLookupUri(

cursor.getLong(idColumn),

cursor.getString(lookupKeyColumn)

)

mBadge.assignContactUri(contactUri)

}Java

// The Cursor that contains contact rows

Cursor mCursor;

// The index of the _ID column in the Cursor

int idColumn;

// The index of the LOOKUP_KEY column in the Cursor

int lookupKeyColumn;

// A content URI for the desired contact

Uri contactUri;

// 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

idColumn = mCursor.getColumnIndex(ContactsContract.Contacts._ID);

// Gets the LOOKUP_KEY index

lookupKeyColumn = mCursor.getColumnIndex(ContactsContract.Contacts.LOOKUP_KEY);

// Gets a content URI for the contact

contactUri =

Contacts.getLookupUri(

mCursor.getLong(idColumn),

mCursor.getString(lookupKeyColumn)

);

mBadge.assignContactUri(contactUri);

当用户点击

设置照片缩略图

注意:3.0 之前的平台版本中没有

Kotlin

// The column in which to find the thumbnail ID

var thumbnailColumn: Int = 0

/*

* The thumbnail URI, expressed as a String.

* Contacts Provider stores URIs as String values.

*/

var thumbnailUri: String? = null

...

mCursor?.let { cursor ->

/*

* Gets the photo thumbnail column index if

* platform version >= Honeycomb

*/

thumbnailColumn = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {

cursor.getColumnIndex(ContactsContract.Contacts.PHOTO_THUMBNAIL_URI)

// Otherwise, sets the thumbnail column to the _ID column

} else {

idColumn

}

/*

* Assuming the current Cursor position is the contact you want,

* gets the thumbnail ID

*/

thumbnailUri = cursor.getString(thumbnailColumn)

}Java

// The column in which to find the thumbnail ID

int thumbnailColumn;

/*

* The thumbnail URI, expressed as a String.

* Contacts Provider stores URIs as String values.

*/

String thumbnailUri;

...

/*

* Gets the photo thumbnail column index if

* platform version >= Honeycomb

*/

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {

thumbnailColumn =

cursor.getColumnIndex(ContactsContract.Contacts.PHOTO_THUMBNAIL_URI);

// Otherwise, sets the thumbnail column to the _ID column

} else {

thumbnailColumn = idColumn;

}

/*

* Assuming the current Cursor position is the contact you want,

* gets the thumbnail ID

*/

thumbnailUri = cursor.getString(thumbnailColumn);

...

定义一种方法,用于获取与联系人照片相关的数据以及目标视图的尺寸,并以

Kotlin

/**

* 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 fun loadContactPhotoThumbnail(photoData: String): Bitmap? {

// Creates an asset file descriptor for the thumbnail file.

var afd: AssetFileDescriptor? = null

// try-catch block for file not found

try {

// Creates a holder for the URI.

val thumbUri: Uri = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {

// If Android 3.0 or later

// Sets the URI from the incoming PHOTO_THUMBNAIL_URI

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)

*/

val contactUri: Uri =

Uri.withAppendedPath(ContactsContract.Contacts.CONTENT_URI, photoData)

/*

* Creates a photo URI by appending the content URI of

* Contacts.Photo.

*/

Uri.withAppendedPath(contactUri, ContactsContract.Contacts.Photo.CONTENT_DIRECTORY)

}

/*

* Retrieves an AssetFileDescriptor object for the thumbnail

* URI

* using ContentResolver.openAssetFileDescriptor

*/

afd = activity?.contentResolver?.openAssetFileDescriptor(thumbUri, "r")

/*

* Gets a file descriptor from the asset file descriptor.

* This object can be used across processes.

*/

return afd?.fileDescriptor?.let {fileDescriptor ->

// Decode the photo file and return the result as a Bitmap

// If the file descriptor is valid

BitmapFactory.decodeFileDescriptor(fileDescriptor, null, null)

}

} catch (e: FileNotFoundException) {

/*

* Handle file not found errors

*/

null

} finally {

// In all cases, close the asset file descriptor

try {

afd?.close()

} catch (e: IOException) {

}

}

}Java

/**

* 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(

ContactsContract.Contacts.CONTENT_URI, photoData);

/*

* Creates a photo URI by appending the content URI of

* Contacts.Photo.

*/

thumbUri =

Uri.withAppendedPath(

contactUri, ContactsContract.Contacts.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() 方法以获取缩略图

Kotlin

...

/*

* Decodes the thumbnail file to a Bitmap.

*/

mThumbnailUri?.also { thumbnailUri ->

loadContactPhotoThumbnail(thumbnailUri).also { thumbnail ->

/*

* Sets the image in the QuickContactBadge

* QuickContactBadge inherits from ImageView, so

*/

badge.setImageBitmap(thumbnail)

}

}Java

...

/*

* Decodes the thumbnail file to a Bitmap.

*/

Bitmap mThumbnail =

loadContactPhotoThumbnail(thumbnailUri);

/*

* Sets the image in the QuickContactBadge

* QuickContactBadge inherits from ImageView, so

*/

badge.setImageBitmap(mThumbnail);

将 QuickContactBadge 添加到 ListView

添加 QuickContactBadge 元素

首先,将

android:layout_width="match_parent"

android:layout_height="wrap_content">

android:id="@+id/quickcontact"

android:layout_height="wrap_content"

android:layout_width="wrap_content"

android:scaleType="centerCrop"/>

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"/>

在以下各部分内容中,此文件称为 contact_item_layout.xml。

设置自定义 CursorAdapter

您定义的

扩充一个新的

您必须替换此方法,才能获取各个子

将数据从当前的

以下代码段举例说明了

定义自定义列表适配器

Kotlin

/**

* 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 data class ViewHolder(

internal var displayname: TextView? = null,

internal var quickcontact: QuickContactBadge? = null

)

/**

*

*

*/

private inner class ContactsAdapter(

context: Context,

val inflater: LayoutInflater = LayoutInflater.from(context)

) : CursorAdapter(context, null, 0) {

...

override fun newView(

context: Context,

cursor: Cursor,

viewGroup: ViewGroup

): View {

/* 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.

*/

return inflater.inflate(

R.layout.contact_list_layout,

viewGroup,

false

).also { view ->

view.tag = ViewHolder().apply {

displayname = view.findViewById(R.id.displayname)

quickcontact = view.findViewById(R.id.quickcontact)

}

}

}

...

override fun bindView(view: View?, context: Context?, cursor: Cursor?) {

(view?.tag as? ViewHolder)?.also { holder ->

cursor?.apply {

...

// Sets the display name in the layout

holder.displayname?.text = getString(displayNameIndex)

...

/*

* Generates a contact URI for the QuickContactBadge.

*/

ContactsContract.Contacts.getLookupUri(

getLong(idIndex),

cursor.getString(lookupKeyIndex)

).also { contactUri ->

holder.quickcontact?.assignContactUri(contactUri)

}

getString(photoDataIndex)?.also {photoData ->

/*

* Decodes the thumbnail file to a Bitmap.

* The method loadContactPhotoThumbnail() is defined

* in the section "Set the Contact URI and Thumbnail"

*/

loadContactPhotoThumbnail(photoData)?.also { thumbnailBitmap ->

/*

* Sets the image in the QuickContactBadge

* QuickContactBadge inherits from ImageView

*/

holder.quickcontact?.setImageBitmap(thumbnailBitmap)

}

}

}

}

}

}Java

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(photoDataIndex);

final String displayName =

cursor.getString(displayNameIndex);

...

// Sets the display name in the layout

holder.displayname = cursor.getString(displayNameIndex);

...

/*

* Generates a contact URI for the QuickContactBadge.

*/

final Uri contactUri = Contacts.getLookupUri(

cursor.getLong(idIndex),

cursor.getString(lookupKeyIndex));

holder.quickcontact.assignContactUri(contactUri);

String photoData = cursor.getString(photoDataIndex);

/*

* 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);

}

设置变量

在您的代码中设置变量,包括内含必要列的

注意:以下代码段使用方法 loadContactPhotoThumbnail(),该方法是在设置联系人 URI 和缩略图部分中定义的

例如:

Kotlin

/*

* Defines a projection based on platform version. This ensures

* that you retrieve the correct columns.

*/

private val PROJECTION: Array = arrayOf(

ContactsContract.Contacts._ID,

ContactsContract.Contacts.LOOKUP_KEY,

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {

ContactsContract.Contacts.DISPLAY_NAME_PRIMARY

} else {

ContactsContract.Contacts.DISPLAY_NAME

},

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {

ContactsContract.Contacts.PHOTO_FILE_ID

} else {

/*

* Although it's not necessary to include the

* column twice, this keeps the number of

* columns the same regardless of version

*/

ContactsContract.Contacts._ID

}

)

...

class ContactsFragment : Fragment(), LoaderManager.LoaderCallbacks {

...

// Defines a ListView

private val listView: ListView? = null

// Defines a ContactsAdapter

private val adapter: ContactsAdapter? = null

...

// Defines a Cursor to contain the retrieved data

private val cursor: Cursor? = null

/*

* 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 val idIndex = 0

// Column index of the LOOKUP_KEY column

private val lookupKeyIndex = 1

// Column index of the display name column

private val displayNameIndex = 3

/*

* Column index of the photo data column.

* It's PHOTO_THUMBNAIL_URI for Honeycomb and later,

* and _ID for previous versions.

*/

private val photoDataIndex: Int =

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) 3 else 0

...Java

public class ContactsFragment extends Fragment implements

LoaderManager.LoaderCallbacks {

...

// Defines a ListView

private ListView listView;

// Defines a ContactsAdapter

private ContactsAdapter adapter;

...

// Defines a Cursor to contain the retrieved data

private Cursor cursor;

/*

* Defines a projection based on platform version. This ensures

* that you retrieve the correct columns.

*/

private static final String[] PROJECTION =

{

ContactsContract.Contacts._ID,

ContactsContract.Contacts.LOOKUP_KEY,

(Build.VERSION.SDK_INT >=

Build.VERSION_CODES.HONEYCOMB) ?

ContactsContract.Contacts.DISPLAY_NAME_PRIMARY :

ContactsContract.Contacts.DISPLAY_NAME

(Build.VERSION.SDK_INT >=

Build.VERSION_CODES.HONEYCOMB) ?

ContactsContract.Contacts.PHOTO_FILE_ID :

/*

* Although it's not necessary to include the

* column twice, this keeps the number of

* columns the same regardless of version

*/

ContactsContract.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 idIndex = 0;

// Column index of the LOOKUP_KEY column

private int lookupKeyIndex = 1;

// Column index of the display name column

private int displayNameIndex = 3;

/*

* Column index of the photo data column.

* It's PHOTO_THUMBNAIL_URI for Honeycomb and later,

* and _ID for previous versions.

*/

private int photoDataIndex =

Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB ?

3 :

0;

...

设置 ListView

Kotlin

override fun onCreateView(

inflater: LayoutInflater,

container: ViewGroup?,

savedInstanceState: Bundle?

): View? {

return inflater.inflate(...).let { view ->

...

/*

* Gets a handle to the ListView in the file

* contact_list_layout.xml

*/

listView = view.findViewById(R.id.contact_list)

mAdapter?.also {

listView?.adapter = it

}

...

}

}

...Java

@Override

public View onCreateView(LayoutInflater inflater,

ViewGroup container, Bundle savedInstanceState) {

View view = inflater.inflate(...)

...

/*

* Gets a handle to the ListView in the file

* contact_list_layout.xml

*/

listView = (ListView) view.findViewById(R.id.contact_list_view);

if (listView != null && adapter != null) {

listView.setAdapter(adapter);

}

...

}

...

在 ContactsAdapter 绑定到

Kotlin

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {

super.onViewCreated(view, savedInstanceState)

/*

* Instantiates the subclass of

* CursorAdapter

*/

mAdapter = activity?.let {

ContactsAdapter(it).also { adapter ->

// Sets up the adapter for the ListView

listView?.adapter = adapter

}

}

}Java

@Override

public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {

...

/*

* Instantiates the subclass of

* CursorAdapter

*/

mAdapter = new ContactsAdapter(getActivity());

// Sets up the adapter for the ListView

if (listView != null && mAdapter != null) {

listView.setAdapter(mAdapter);

}

...

}

...

Kotlin

override fun onLoadFinished(loader: Loader, cursor: Cursor) {

// When the loader has completed, swap the cursor into the adapter.

mAdapter?.swapCursor(cursor)

}Java

public void onLoadFinished(Loader loader, Cursor cursor) {

// When the loader has completed, swap the cursor into the adapter.

mAdapter.swapCursor(cursor);

}

Kotlin

override fun onLoaderReset(loader: Loader) {

// Removes remaining reference to the previous Cursor

adapter?.swapCursor(null)

}Java

@Override

public void onLoaderReset(Loader loader) {

// Removes remaining reference to the previous Cursor

adapter.swapCursor(null);

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值