7.结果显示
问题:1,加载联系人时,联系人前面有 A,B,C等等,查询时的结果都没有
2,联系人前面ABC的大写字母颜色不一样
3,加载联系人仅显示姓名,Dialer查询时还会显示号码,Contacts查询时,
如果邮箱和号码匹配,才显示,否则仅仅显示姓名。什么,邮箱也可以查询?
7.1联系人前面的ABC字符
字符查询流程
ContactsProvider2查询时,将字符查询后通过
FastScrollingIndexCache写入到Bundle中,然后将该Bundle塞入Cursor中。
流程如下:
以下是buildExtraBundle函数, 和下面在Bundle中取出一目了然。
public static final Bundle buildExtraBundle(String[] titles, int[] counts) {
Bundle bundle = new Bundle();
bundle.putStringArray(Contacts.EXTRA_ADDRESS_BOOK_INDEX_TITLES, titles);
bundle.putIntArray(Contacts.EXTRA_ADDRESS_BOOK_INDEX_COUNTS,counts);
return bundle; }
该数据在数据更新的时候(增加/删除/修改/查询)都会调用,所以可以实时显示。
字符查询后写入流程
ContactEntryListFragment.java中的onLoadFinished将查询到的ABC字符信息写入到ContactsSectionIndexer类中的流程如下:
在updateIndexer函数中,
String sections[]=
bundle.getStringArray(Contacts.EXTRA_ADDRESS_BOOK_INDEX_TITLES);
int counts[]= bundle.getIntArray(Contacts.EXTRA_ADDRESS_BOOK_INDEX_COUNTS);
sections 字符数组中存储的自然是 ABCDEF等等
counts 数组存储对应的字符的联系人的个数。
ContactsSectionIndexer中三个实例,
privateString[] mSections; // ABCD等字符串数组
private int[]mPositions;// 是counts对应位置元素的累加。
表示的是在哪些联系人前面显示对应的字符,比如在55到87位置显示 F
// 在后面的显示中会用到这个转换,这个算法还是有点小复杂
private intmCount;// 所有联系人的个数
疑惑6:这两个数组应该在查询联系人时就设置进去了,但是在哪儿设置进去的呢
Android 5.0 汉字不能识别,前面显示 #
Android 6.0 可以识别汉字,比如,伯伯 前面显示 B
字符显示流程
加载联系人时,虽然DefaultContactListAdapter和PhoneNumberListAdapter都调用bindSectionHeaderAndDivider函数,但是有同一个判断条件
isSectionHeaderDisplayEnabled,在加载联系人时,该值为true,在查询联系人时,该值为false,所以该字符在加载和查询时的显示有区别。
在getItemPlacementInSection函数中,进行相关算法,如果联系人所在位置是第一个就显示的字符就显示,否则就显示空字符。
7.2联系人图标显示
PhoneNumberListAdapter里面的bindView函数调用的是bindQuickContact
(QuickContactBadge),DefaultContactListAdapter调用了bindPhoto(ImageView)函数,但是其他流程一模一样。在各自对应的Fragement里面调用setQuickContactEnabled来设置。在这里仅描述DefaultContactListAdapter的流程。
bindPhoto函数中,首先判断该联系人是否有自带的图像,如果有就调用
loadThumbnail函数将图像加载并显示为原型的图标;如果没有图像,就调用
loadDirectoryPhoto函数设置默认图标。这里面两个类比较重要,
DefaultImageRequest和LetterTileDrawable。DefaultImageRequest的实例
displayName(联系人的名字), identifier(联系人的唯一标识符),并且通过
setContactDetails传送到LetterTileDrawable类中。
ImageView类的onDraw函数里面会调用Drawable(LetterTileDrawable)的draw函数。在drawLetterTile( )中完成图标以及字符的显示,首先设置颜色,一共有14中颜色,定义在ContactsCommon/res/values/colors.xml / letter_tile_colors
得到颜色的方法: final int color = Math.abs(identifier.hashCode())% sColors.length().
然后根据mDisplayName来判断第一个字符是否为英语字母,如果不是,则显示默认的图标,否则将字符转化为大写字母后显示在图标上。
7.3联系人相关信息显示
这是contacts查询联系人时的序列图.在DefaultContactListAdapter的bindView函数中,
bindNameAndViewId(view,cursor); // 显示姓名
bindPresenceAndStatusMessage(view,cursor);// 显示联系人后面的拨号图标
if(isSearchMode()) {
bindSearchSnippet(view, cursor);// 处于查询状态时,显示号码或者其他
} else {
view.setSnippet(null);//处于没有查询的状态,不显示号码或者其他
}
bindPresenceAndStatusMessage,只有contact才显示联系人后面的图标。
显示总结
MultiSelectContactsListFragment以及AllContactsFragment通过
DefaultContactListAdapter调用bindView来显示。
疑惑:为啥AllContactsFragment联系人没有后面的拨号图标?
SmartDialSearchFragment和RegularSearchFragment通过
PhoneNumberListAdapter调用bindView来显示。在该bindView函数中,
bindName(view,cursor); // 显示姓名
bindPhoneNumber(view,cursor, directory.isDisplayNumber());// 显示电话号码
bindQuickContact() // 显示联系人前面的图标。
搜索时,显示结果匹配的地方加了渲染,通过SpannableString和TextHighlighter来完成。