点击通话记录的item,下面会弹出一些选项,例如,为该通话记录新建一个联系人,添加一个联系人,发送短信,或者查看通话详情。在此主要看通话详情的实现。
添加通话详情的intent调用流程图如下,
CallLogListItemViewHolder的showActions方法主要逻辑如下,
1,设置界面可见,
inflateActionViewStub();
actionsView.setVisibility(View.VISIBLE);
actionsView.setAlpha(1.0f);
2,显示界面的详细信息,
updatePrimaryActionButton(show);
inflateActionViewStub方法主要逻辑如下,
1,添加新建联系人等的监听事件,
ViewStub stub = (ViewStub) rootView.findViewById(R.id.call_log_entry_actions_stub);
•••
callButtonView = actionsView.findViewById(R.id.call_action);
callButtonView.setOnClickListener(this); //拨号监听事件
videoCallButtonView = actionsView.findViewById(R.id.video_call_action);
videoCallButtonView.setOnClickListener(this); //视频通话监听事件
createNewContactButtonView = actionsView.findViewById(R.id.create_new_contact_action);
createNewContactButtonView.setOnClickListener(this);//新建联系人监听事件
addToExistingContactButtonView =
actionsView.findViewById(R.id.add_to_existing_contact_action);
addToExistingContactButtonView.setOnClickListener(this); //添加到已有联系人监听事件
sendMessageView = actionsView.findViewById(R.id.send_message_action);
sendMessageView.setOnClickListener(this); //发送短信监听事件
detailsButtonView = actionsView.findViewById(R.id.details_action);
detailsButtonView.setOnClickListener(this); //通话详情监听事件
•••
2,调用bindActionButtons方法为监听事件添加intent,
bindActionButtons();
bindActionButtons方法逻辑如下,
1,调用IntentProvider的getReturnCallIntentProvider方法添加拨号的intent
callButtonView.setTag(IntentProvider.getReturnCallIntentProvider(number));
2,调用IntentProvider的getReturnVideoCallIntentProvider方法添加视频拨号的intent,
videoCallButtonView.setTag(IntentProvider.getReturnVideoCallIntentProvider(number));
3,调用IntentProvider的getCallDetailIntentProvider方法为通话详情添加intent,
detailsButtonView.setTag(IntentProvider.getCallDetailIntentProvider(rowId, callIds, null));
4,添加 新建一个联系人/添加到联系人 的intent,并确定是否显示这2个view,
if (info != null && UriUtils.isEncodedContactUri(info.lookupUri)) {
createNewContactButtonView.setTag(IntentProvider.getAddContactIntentProvider(
info.lookupUri, info.name, info.number, info.type, true /* isNewContact */));
createNewContactButtonView.setVisibility(View.VISIBLE);
addToExistingContactButtonView.setTag(IntentProvider.getAddContactIntentProvider(
info.lookupUri, info.name, info.number, info.type, false /* isNewContact */));
addToExistingContactButtonView.setVisibility(View.VISIBLE);
} else {
createNewContactButtonView.setVisibility(View.GONE);
addToExistingContactButtonView.setVisibility(View.GONE);
}
如果通话号码可以在联系人里面查询到,当然就不显示了;否则就显示。
5, 调用IntentProvider的getSendSmsIntentProvider方法添加发送短信的intent,
sendMessageView.setTag(IntentProvider.getSendSmsIntentProvider(number));
在此主要论述的是通话详情,因此主要看IntentProvider的getCallDetailIntentProvider方法,如下,
return new IntentProvider() {
@Override
public Intent getIntent(Context context) {
Intent intent = new Intent(context, CallDetailActivity.class);
// Check if the first item is a voicemail.
if (voicemailUri != null) {
intent.putExtra(CallDetailActivity.EXTRA_VOICEMAIL_URI, Uri.parse(voicemailUri));
}
if (extraIds != null && extraIds.length > 0) {// 包含多条通话信息
intent.putExtra(CallDetailActivity.EXTRA_CALL_LOG_IDS, extraIds);
} else {
// If there is a single item, use the direct URI for it. //单条通话信息
intent.setData(ContentUris.withAppendedId(TelecomUtil.getCallLogUri(context), id));
}
return intent;
}
};
IntentProvider只是一个abstract类,有一个抽象的getIntent方法,
public abstract Intent getIntent(Context context);
在获取每个intent的方法中,都是返回一个匿名IntentProvider类,并且实现了getIntent方法。
这只是初始化步骤。
在CallLogAdapter的createCallLogEntryViewHolder方法中,会调用CallLogListItemViewHolder的create方法获取CallLogListItemViewHolder对象,会将mExpandCollapseListener监听器做为参数传入, CallLogListItemViewHolder的构造方法部分如下,
primaryActionView.setOnClickListener(mExpandCollapseListener);
并且在CallLogListItemViewHolder的onClick方法中,
1,当点击通话记录item时,
mExpandCollapseListener.onClick(primaryActionView);
就会回调CallLogAdapter的mExpandCollapseListener监听器的onClick方法。
这样才可以展示如下界面,
2,点击如上界面之后的onclick方法逻辑如下,
首先调用view的getTag方法获取IntentProvider对象,存储的时候就是调用setTag方法进行的。然后调用IntentProvider的getIntent方法获取Intent对象;最后调用DialerUtils的startActivityWithErrorToast方法完成处理。
final IntentProvider intentProvider = (IntentProvider) view.getTag();
if (intentProvider != null) {
final Intent intent = intentProvider.getIntent(mContext);
// See IntentProvider.getCallDetailIntentProvider() for why this may be null.
if (intent != null) {
DialerUtils.startActivityWithErrorToast(mContext, intent);
}
}
DialerUtils的startActivityWithErrorToast方法主要逻辑如下,
1,处理拨号,
if ((IntentUtil.CALL_ACTION.equals(intent.getAction())
&& context instanceof Activity)) {
2,处理其他请求,
context.startActivity(intent);
CallLogAdapter的mExpandCollapseListener是View.OnClickListener匿名实现类,其onClick方法如下,
if (viewHolder.getAdapterPosition() == mCurrentlyExpandedPosition) {
// Hide actions, if the clicked item is the expanded item.
viewHolder.showActions(false);
mCurrentlyExpandedPosition = RecyclerView.NO_POSITION;
mCurrentlyExpandedRowId = NO_EXPANDED_LIST_ITEM;
} else {
expandViewHolderActions(viewHolder);
}
如果显示菜单已打开,就调用CallLogListItemViewHolder的showActions方法将其隐藏;
如果未显示,就调用expandViewHolderActions方法显示,该方法如下,
viewHolder.showActions(true);
mCurrentlyExpandedPosition = viewHolder.getAdapterPosition();
mCurrentlyExpandedRowId = viewHolder.rowId;
也是调用CallLogListItemViewHolder的showActions方法将其显示。
CallLogListItemViewHolder的showActions方法有一个boolean参数,如果参数为true就显示,否则就隐藏。