短信ui-会话编辑界面(二)接收者UI
16lz
2021-01-25
短信ui-会话编辑界面(二)接收者UI
1、前沿
通过前面http://blog.csdn.net/ceko_wu/article/details/8201193 基础知识的学习,接收者UI 比较简单,下面就来看看它的功能是怎么实现的。
2、功能分析
这个UI 是很简单的,上篇文章有简单介绍,只有当新建会话的时候才会显示该UI,打开已存在的会话不会显示该UI。
LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal"> <ViewStub android:id="@+id/recipients_editor_stub" android:layout="@layout/recipients_editor" android:layout_width="0dip" android:layout_height="wrap_content" android:layout_weight="1.0" /> <ViewStub android:id="@+id/add_recipients_bt_stub" android:layout="@layout/add_recipients_bt" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginLeft="5dip" /> </LinearLayout> <EditText android:id="@+id/subject" android:layout_width="match_parent" android:layout_height="wrap_content" android:capitalize="sentences" android:autoText="true" android:singleLine="true" android:maxLength="40" android:hint="@string/subject_hint" android:visibility="gone"/>从上面布局文件来看也就三个,其中主题UI很简单所以不做具体分析:
2.1 是接收者编辑框简介
该编辑框不是一个简单的EditTextview,通过看 layout/recipients_editor你可以发现<com.android.mms.ui.RecipientsEditor xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/recipients_editor" android:hint="@string/to_hint" android:layout_width="match_parent" android:layout_height="wrap_content" android:inputType="textFilter" />查看RecipientsEditor类
public class RecipientsEditor extends MultiAutoCompleteTextView {
这里大家可能比较疑惑,为什么不使用一般的EditTextView,而使用自定义的MultiAutoCompleteTextView ,它与一般的EditTextView的差异:
首先 它可以处理接收者的内容,对于其内容的编辑处理,添加联系人有两种方式:一是手动编写,二是从通讯录中添加联系人。其次是该类有一个自动提供建议的功能,例如用户输入100,程序会去检索100相关的联系人并显示,用户根据自己的要求选择,类似于自动补全功能。
2.2 编辑框 对联系人的处理
首先来看看该UI初始化的时候做了哪些操作,设置了哪些监听。private void initRecipientsEditor() { ContactList recipients = getRecipients(); ViewStub stub = (ViewStub)findViewById(R.id.recipients_editor_stub); if (stub != null) { mRecipientsEditor = (RecipientsEditor) stub.inflate(); } else { mRecipientsEditor = (RecipientsEditor)findViewById(R.id.recipients_editor);初始化编辑框 mRecipientsEditor.setVisibility(View.VISIBLE); } stub = (ViewStub)findViewById(R.id.add_recipients_bt_stub);初始化添加按钮 mAddRecipientButton.setOnClickListener(this);添加按钮设置监听器 mRecipientsEditor.setAdapter(new RecipientsAdapter(this));设置自动补全的adapter mRecipientsEditor.populate(recipients);同步联系人 mRecipientsEditor.setOnCreateContextMenuListener(mRecipientsMenuCreateListener);设置长按menu mRecipientsEditor.addTextChangedListener(mRecipientsWatcher);设置文件watcher mRecipientsEditor.setOnItemClickListener(new AdapterView.OnItemClickListener() {用户点击联系人子项时的点击事件处理 public void onItemClick(AdapterView<?> parent, View view, int position, long id) { if (mRecipientsEditor.getRecipientCount() == 1) { final InputMethodManager inputManager = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE); if (inputManager == null || !inputManager.isFullscreenMode()) { mTextEditor.requestFocus(); } }}}); mRecipientsEditor.setOnFocusChangeListener(new View.OnFocusChangeListener() {当foucus状态发生变化时更新activity的title public void onFocusChange(View v, boolean hasFocus) { if (!hasFocus) { RecipientsEditor editor = (RecipientsEditor) v; ContactList contacts = editor.constructContactsFromInput(); updateTitle(contacts); } } });上面做了两个重要的操作,一个是设置自动补全的adapter,另一个是设置文本的watcher。
2.2.1 文本watcher
首先来看看设置的文本watcher有什么作用,实现了哪些功能.private final TextWatcher mRecipientsWatcher = new TextWatcher() { public void beforeTextChanged(CharSequence s, int start, int count, int after) { } public void onTextChanged(CharSequence s, int start, int before, int count) { onUserInteraction(); } public void afterTextChanged(Editable s) { if (!isRecipientsEditorVisible()) { IllegalStateException e = new IllegalStateException( "afterTextChanged called with invisible mRecipientsEditor"); return; } mWorkingMessage.setWorkingRecipients(mRecipientsEditor.getNumbers()); mWorkingMessage.setHasEmail(mRecipientsEditor.containsEmail(), true); checkForTooManyRecipients(); updateTitle(mRecipientsEditor.constructContactsFromInput()); for (int pos = s.length() - 1; pos >= 0; pos--) { char c = s.charAt(pos); if (c == ' ') continue; if (c == ',') { updateTitle(mConversation.getRecipients()); } break; } updateSendButtonState(); } };该watcher做的工作很简单,就是讲添加的联系人同步,检查联系人是否查出限制,更新title,更新发送按钮的状态。
2.2.2 自动补全功能
自动补全是怎么实现的,来看看设置的adapter,之所以没有讲这个adapter是怎么和控件来实现的,其内部原理没有讲解,是因为这里的控件是MultiAutoCompleteTextView ,该控件就是自带这个功能,在sdk中有相关说明,所以这里就不做进一步分析。那该adpater就是用于将查询出的相关的联系人绑定到view上显示。@Override public Cursor runQueryOnBackgroundThread(CharSequence constraint) { String phone = ""; String cons = null; if (constraint != null) { cons = constraint.toString(); if (usefulAsDigits(cons)) { phone = PhoneNumberUtils.convertKeypadLettersToDigits(cons); if (phone.equals(cons)) { phone = ""; } else { phone = phone.trim();}} } Cursor phoneCursor = mContentResolver.query(uri, PROJECTION_PHONE, null, //selection, null, SORT_ORDER); if (phone.length() > 0) { ArrayList result = new ArrayList(); result.add(Integer.valueOf(-1)); // ID result.add(Long.valueOf(-1)); // CONTACT_ID result.add(Integer.valueOf(Phone.TYPE_CUSTOM)); // TYPE result.add(phone); // NUMBER result.add("\u00A0"); // LABEL result.add(cons); // NAME ArrayList<ArrayList> wrap = new ArrayList<ArrayList>(); wrap.add(result); ArrayListCursor translated = new ArrayListCursor(PROJECTION_PHONE, wrap); return new MergeCursor(new Cursor[] { translated, phoneCursor }); } else { return phoneCursor; } }查询用户输入相关的联系人,然后绑定view
@Override public final void bindView(View view, Context context, Cursor cursor) { TextView name = (TextView) view.findViewById(R.id.name); name.setText(cursor.getString(NAME_INDEX)); TextView label = (TextView) view.findViewById(R.id.label); int type = cursor.getInt(TYPE_INDEX); CharSequence labelText = Phone.getDisplayLabel(mContext, type, cursor.getString(LABEL_INDEX)); if (labelText.length() == 0 || (labelText.length() == 1 && labelText.charAt(0) == '\u00A0')) { label.setVisibility(View.GONE); } else { label.setText(labelText); label.setVisibility(View.VISIBLE); } TextView number = (TextView) view.findViewById(R.id.number); number.setText(cursor.getString(NUMBER_INDEX)); }这里基本上完成了自动补全的功能,具体细节大家可以看看具体代码。
2.3 添加联系人button处理
添加联系人button处理,查看对应监听器代码if (v == mAddRecipientButton) { if (recipientCount() < recipientLimit) {Intent intent = new Intent(ACTION_MULTI_PICK,Contacts.CONTENT_URI);startActivityForResult(intent, REQUEST_CODE_PICK_CONTACT);} else {checkAddTooManyRceiver(recipientCount());} }这里做了一个联系人数量的检查,当然正常情况会跳转到联系人界面选择添加的联系人,至于联系人这个app怎么做的这里不做太多的分析。那添加过后联系人的信息就会返回给当前界面,在onActivitiyResult方法里做的处理。这里简单分析该方法对联系人信息的处理;
case REQUEST_CODE_PICK_CONTACT: Bundle b = data.getExtras(); Bundle contactSet = b.getBundle("result"); Set<String> set = contactSet.keySet(); Iterator<String> i = set.iterator(); if (mRecipientsEditor != null) { addRecipientsListeners(); ContactList list = mRecipientsEditor .constructContactsFromInput(); int add_count = 0; if (list.size() + set.size() > recipientLimit) { checkAddTooManyRceiver(list.size() + set.size()); add_count = recipientLimit - list.size(); } else { add_count = set.size(); } int flag = 0; while (i.hasNext()) { if (flag < add_count) { String key = i.next(); list.add(Contact.get( contactSet.getStringArray(key)[NUMBER_INDEX], false)); flag++; } else { break; } } mRecipientsEditor.populate(list); } break;这里做的很简单通过返回的联系人信息同步到ui上,populate方法做这件事情
public void populate(ContactList list) { SpannableStringBuilder sb = new SpannableStringBuilder(); for (Contact c : list) { if (sb.length() != 0) { sb.append(", "); } sb.append(contactToToken(c)); } setText(sb); }
3、总结
接收者ui其操作很简单,就是显示联系人或者提供给用户编辑联系人。
更多相关文章
- Android(安卓)Activity 和 Task 设计指导
- Android文档学习03_Intent
- Android学习 之 应用程序基础及四大组件
- Android基础笔记(九)- 广播
- 一个公开了源码的Android(安卓)UI 设计器,很好很强大,不知道的可以
- Android(安卓)Phonebook编写联系人UI加载及联系人保存流程(一)
- android 获取上一个activity的返回值
- Android活动文件夹
- Android实现自定义listview上拉刷新下拉加载以及侧滑编辑、删除