短信模块
修改 选择 添加联系人
主界面中的控件 选择view RecipientsEditor 继承 RecipientEditTextView
查询了以后才知道这是 系统 framework层的一个控件(后查看androd.mk 文件确实有引用)
framework/opt/chips/src/com/android/ex/chips 涉及 Mms Email Calanda
打log 看日志信息,
1.当在控件上 默认填写 联系人首字母的时候,他会取数据库查询相关数据,显示(能显示 联系人头像,名称),点击选择后 也能显示 联系人头像和名称
2. 当点击控件右边的选择按钮时,跳入 联系人模块,去选择,但是选择完成后,无联系人头像的信息
一开是判断的是,头像数据在 onAcitivtyresult 的返回结果中,没有返回
首先去看 framework层 这个系统控件 显示头像的原理
第一种方式, 他在 你输入首字母时,会出来选择列表( 有 头像,联系人名称,电话), 点击确定后会展示 ( 头像,联系人名称)
1.显示的联系人集合列表 其实是
ContactDropdownLayouter 继承 framework的 DropdownChipLayouter
(数据的查询是在adapter中进行的)
调用继承的方法
//绑定text
@Override
protected void bindTextToView(CharSequence text, TextView view) {
}
// 绑定icon
@Override
protected void bindIconToView(boolean showImage, RecipientEntry entry, ImageView view,
AdapterType type) {
}
- 找到了点击方法 RecipientsEditor 中的 onItemClick
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
super.onItemClick(parent, view, position, id);
if (mOnSelectChipRunnable != null) {
mOnSelectChipRunnable.run();
}
}
其实 super.onItemClick(parent, view, position, id); 这个才是重点的方法
调用父类 RecipientEditTextView 的选择点击事件,
进入 framework 控件中的 onItemClick 方法
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
if (position < 0) {
return;
}
final int charactersTyped = submitItemAtPosition(position);
if (charactersTyped > -1 && mRecipientEntryItemClickedListener != null) {
mRecipientEntryItemClickedListener
.onRecipientEntryItemClicked(charactersTyped, position);
}
}
进入 submitItemAtPosition 中的 createChip()
进入 createChip() 中的核心方法 进行图片的创建和绘制, 完成后,变成 SpannableString 进行返回
final SpannableString chipText = new SpannableString(displayText);
// create background and text and usericon
DrawableRecipientChip chip = constructChipSpan(entry);
// add chip
chipText.setSpan(chip, 0, textLength,
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
chip.setOriginalText(chipText.toString());
chip.setOriginalText(chipText.toString());
第二种方式, 就先看有没有img的数据获取到了 在主activity 中onActivityResult 先清理之前的数据 asyncDeleteDraftSmsMessage() 进行数据处理,获取数据
processPickResult() -> processAddRecipients() -> list = ContactList.blockingGetByUris(buildUris(keySet, newPickRecipientsCount));
进入 Contact.java blockingGetByUris() Contact contact = Contact.get(uri.getSchemeSpecificPart(), true);
继续跟入 updateContact©中 调用 Contact entry = getContactInfo©;
进入 getContactInfo() 中 调用 getContactInfoForPhoneNumber(strippedNumber);
进入 getContactInfoForPhoneNumber() 去获取了数据并放入 实体
try {
if (cursor.moveToFirst()) {
fillPhoneTypeContact(entry, cursor);
}
} finally {
cursor.close();
}
然后就要显示了
mRecipientsEditor.populate(list);
// Set value for mRecipientsPickList and
// mRecipientsWatcher will update the UI.
mRecipientsPickList = list;
updateTitle(list);
在populate方法中, 将获取到的数据, for循环, 调用 framework控件的 append 方public void
public void populate(ContactList list) {
if (list.size() == 0) {
setText(null);
} else {
setText("");
for (Contact c : list) {
CharSequence charSequence = contactToToken(c);
//get drawable
//从当前app 中获取图片的方式,下拉展示列表用的这个方式
//Drawable avatarDrawable = c.getAvatar(mContext, mContext.getResources().getDrawable(R.drawable.stranger));
if (charSequence != null && charSequence.length() > 0) {
byte[] drawable = c.getMAvatarData();
setMyPhotoBytes(drawable);
// charSequence = hao <192373803883>
append( charSequence+ ", ");
}
}
}
}
有 存取img的变量 byte[] , 添加一个外部能够获取到的方法
在framework层 控件添加 (因为 framework层封装好的控件,人家有自己的实体类, 在显示栏生成 图片和 文字组合的时候,就会判断尸体类中的img 是否有值,有就添加,没有就添加默认的灰色图片)能够赛入img 的方法 ,
一开始很单纯,确实新写了一个方法, 在framework中的控件中 接受 byte[] img 的数据, 最后发现选择一个人的时候,是正常的,选择多人的时候,后面人的图片大家都会一样基本,并且是最后一个人的头像。
原因就是 :
异步线程了,当img赛入后, 第一个联系人还没创建头像的时候, 又开始赛入了图片,就把第一个 byte[] img 接收的值改变了,
最后,跟着代码再看, 还好。 他其中有个 for 循环添加 text 和 background 的方法,
这样我就定义了一个list 接收数据的时候 add 就好了。 在for 循环中取出来, 塞入 framework 控件要绘制时的 实体中,这样实体有数据了, 就可以显示头像了
handlePendingChips()
createIconReplacementChip(tokenStart, tokenEnd, editable, i < CHIP_LIMIT
|| !mShouldShrink, wtByte.get(i));
RecipientEntry entry = createTokenizedEntry(token);
entry.setPhotoBytes(icon);