Android Phonebook编写联系人UI加载及联系人保存流程(四)
2014-01-07 10:45
483 查看
2014-01-07 10:23:22 将百度空间里的东西移过来。
5. KindSectionView
KindSectionView是何方神圣呢?它又是怎么怎么和一个DataKind,以及一个RawContactDelta绑定到一起的呢?继续看,进入KindSectionView,其实KindSectionView就是一个普通的自定义View,他的作用还真的就是将DataKind中包含的数据变成UI显示出来,那么这个View是什么呢?它有自己的xml文件:item_kind_section.xml:
对照这图片我们分析:
kind_title_layout:就是上图中的Phone那个View;
add_text:就是上图中的“Add new” Button;
kind_editors:就是介于这两者之间的部分。当然,对add_text的点击事件处理也在KindSectionView类,如下:
不过我们还是继续沿着KindSectionView类setState()方法往下分析,rebuildFromState()-->createEditorView(),createEditorView()方法具体加载了每一个DataKind,代码如下:
首先是mKind,这个值就是section.setState(kind, state, false, vig)传过来的,它先取出editorLayoutResourceId,然后解析为View,并绑定在mEditors上,然后再操作,那么editorLayoutResourceId是什么?我们回过头去看DataKind:
DataKind有两个默认的构造器,无参构造器设置了默认的text_fields_editor_view,以LocalAccountType为例:
添加Name时,使用R.layout.structured_name_editor_view:
添加NickName, Phone, Email等时都是R.layout.text_fields_editor_view。回来接着看createEditorView()方法,
editorLayoutResourceId有了,剩下的就是把这个id对应的layout显示出来,看
editor.setValues(mKind, entry, mState, mReadOnly, mViewIdGenerator);看两个xml文件:
structured_name_editor_view.xml 这个是专门针对Name的,后面再说,先看text_fields_editor_view.xml:
edit_spinner:上图中“Home” Spinner;
expansion_view_container:展开或折叠Button,这个只有在Postal Address和Name中用到;
delete_button_container:上图中的叉;
TextFieldsEditorView类的继承关系如图:
我们进入TextFieldsEditorView的setValues()方法:
首先调用了父类的setValues()方法,在父类的setValues()方法中对一些UI赋值,如Spinner mLabel,给他设置了一个Adapter,值就是kind.typeList中包含的内容,前文中提到过。
我们继续看TextFieldsEditorView的setValues()方法,有个for循环,将kind.fieldList中所有的field取出来,并创建一个对应的EditText fieldView,然后添加到mFields,mFields = (ViewGroup) findViewById(R.id.editors),来自text_fields_editor_view.xml --> edit_field_list_with_anchor_view.xml,如下:
说白了,editors这个id对应的View就是用来添加一个EditText。
稍微总结一下:
最重要的是RawContactCommonEditorView类setState()方法,其中的for循环,作用就是将账户中的每一个kind取出来,然后生成一个KindSectionView,并显示出来。而每一个KindSectionView里面,又有可能包含多个field,这取决于kind中fieldlist中添加的EditField的个数,如下图,就包含2个EditField。
至此,Phone UI的显示部分完成,具体的细节还得要仔细看代码,比如Spinner的点击事件,叉的点击事件,文中有提到,但是具体的还得研究代码,很简单,至于EditText添加的TextChangedListener的作用,这个设计到Save contact,我们先记住每个EditText都有一个TextChangedListener就好,到分析Save Contact流程时再说。
6. 添加Name UI
前面提到Name UI,我们这里仔细分析它。
在raw_contact_editor_view.xml中,有专门添加Name相关UI的布局:
进入structured_name_editor_view.xml:
发现这个文件和text_fields_editor_view.xml很像,当然了,看StructuredNameEditorView类的继承图,发现StructuredNameEditorView继承自TextFieldsEditorView,所以啊,他的逻辑其实也在TextFieldsEditorView里面,和Phone一样,只不过因为StructedName比较特殊,比如没有前面的Title, 后面的“Add new”和Spinner等。我以前做这块的UI定制的时候,需要改变页面中所有的EditText的效果,尤其是有多个EditText,比如Name, Address展开后的效果,其实改动还是在TextFieldsEditorView的setValues()方法中,对EditText设置背景,以及其他属性,来达到定制的需求。
5. KindSectionView
KindSectionView是何方神圣呢?它又是怎么怎么和一个DataKind,以及一个RawContactDelta绑定到一起的呢?继续看,进入KindSectionView,其实KindSectionView就是一个普通的自定义View,他的作用还真的就是将DataKind中包含的数据变成UI显示出来,那么这个View是什么呢?它有自己的xml文件:item_kind_section.xml:
<com.android.contacts.editor.KindSectionView xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginBottom="@dimen/raw_contact_sect_fields_margin_bottom" android:orientation="vertical"> <include android:id="@+id/kind_title_layout" layout="@layout/edit_kind_title" /> <LinearLayout android:id="@+id/kind_editors" android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical" /> <Button android:id="@+id/add_text" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="start" android:text="@string/add_new_entry_for_section" android:drawableStart="@drawable/spb_plus_icn" /> </com.android.contacts.editor.KindSectionView>
对照这图片我们分析:
kind_title_layout:就是上图中的Phone那个View;
add_text:就是上图中的“Add new” Button;
kind_editors:就是介于这两者之间的部分。当然,对add_text的点击事件处理也在KindSectionView类,如下:
@Override protected void onFinishInflate() { setDrawingCacheEnabled(true); setAlwaysDrawnWithCacheEnabled(true); mInflater = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE); mTitle = (TextView) findViewById(R.id.kind_title); mEditors = (ViewGroup) findViewById(R.id.kind_editors); mAddFieldFooter = findViewById(R.id.add_text); mAddFieldFooter.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { mAddFieldFooter.setVisibility(View.GONE); addItem(); } }); super.onFinishInflate(); }
不过我们还是继续沿着KindSectionView类setState()方法往下分析,rebuildFromState()-->createEditorView(),createEditorView()方法具体加载了每一个DataKind,代码如下:
private View createEditorView(ValuesDelta entry) { final View view; try { view = mInflater.inflate(mKind.editorLayoutResourceId, mEditors, false); } catch (Exception e) { } view.setEnabled(isEnabled()); if (view instanceof Editor) { Editor editor = (Editor) view; editor.setDeletable(true); editor.setValues(mKind, entry, mState, mReadOnly, mViewIdGenerator); editor.setEditorListener(this); } mEditors.addView(view); return view; }
首先是mKind,这个值就是section.setState(kind, state, false, vig)传过来的,它先取出editorLayoutResourceId,然后解析为View,并绑定在mEditors上,然后再操作,那么editorLayoutResourceId是什么?我们回过头去看DataKind:
public DataKind() { editorLayoutResourceId = R.layout.text_fields_editor_view; maxLinesForDisplay = 1; } public DataKind(String mimeType, int titleRes, int weight, boolean editable, int editorLayoutResourceId) { this.mimeType = mimeType; this.titleRes = titleRes; this.weight = weight; this.editable = editable; this.typeOverallMax = -1; this.editorLayoutResourceId = editorLayoutResourceId; maxLinesForDisplay = 1; }
DataKind有两个默认的构造器,无参构造器设置了默认的text_fields_editor_view,以LocalAccountType为例:
protected DataKind addDataKindStructuredName( Context context) throws DefinitionException { DataKind kind = addKind(new DataKind(StructuredName.CONTENT_ITEM_TYPE, R.string.nameLabelsGroup, -1, true, R.layout.structured_name_editor_view));
添加Name时,使用R.layout.structured_name_editor_view:
protected DataKind addDataKindNickname( Context context) throws DefinitionException { DataKind kind = addKind(new DataKind(Nickname.CONTENT_ITEM_TYPE, R.string.nicknameLabelsGroup, 115, true, R.layout.text_fields_editor_view));
添加NickName, Phone, Email等时都是R.layout.text_fields_editor_view。回来接着看createEditorView()方法,
editorLayoutResourceId有了,剩下的就是把这个id对应的layout显示出来,看
editor.setValues(mKind, entry, mState, mReadOnly, mViewIdGenerator);看两个xml文件:
structured_name_editor_view.xml 这个是专门针对Name的,后面再说,先看text_fields_editor_view.xml:
<com.android.contacts.editor.TextFieldsEditorView xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical"> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_weight="1" android:orientation="horizontal" android:gravity="center_vertical" android:focusable="true" android:clickable="true"> <include layout="@layout/edit_spinner" android:layout_width="@dimen/editor_type_label_width" android:layout_height="@dimen/editor_min_line_item_height" android:layout_gravity="top" android:layout_marginEnd="@dimen/raw_contact_edit_spinner_margin_end" android:visibility="gone" /> <include layout="@layout/edit_field_list_with_anchor_view" /> <FrameLayout android:layout_width="wrap_content" android:layout_height="match_parent"> <include android:id="@+id/expansion_view_container" layout="@layout/edit_expansion_view" android:visibility="gone" /> <include android:id="@+id/delete_button_container" layout="@layout/edit_delete_button" android:visibility="gone" /> </FrameLayout> </LinearLayout> </com.android.contacts.editor.TextFieldsEditorView>
edit_spinner:上图中“Home” Spinner;
expansion_view_container:展开或折叠Button,这个只有在Postal Address和Name中用到;
delete_button_container:上图中的叉;
TextFieldsEditorView类的继承关系如图:
我们进入TextFieldsEditorView的setValues()方法:
@Override public void setValues(DataKind kind, ValuesDelta entry, RawContactDelta state, boolean readOnly, ViewIdGenerator vig) { super.setValues(kind, entry, state, readOnly, vig); int fieldCount = kind.fieldList.size(); mFieldEditTexts = new EditText[fieldCount]; for (int index = 0; index < fieldCount; index++) { final EditField field = kind.fieldList.get(index); final EditText fieldView = createFieldView(field.column); fieldView.setTextAppearance(getContext(), android.R.style.TextAppearance_Medium); mFieldEditTexts[index] = fieldView; fieldView.addTextChangedListener(new TextWatcher() { @Override public void afterTextChanged(Editable s) { // Trigger event for newly changed value onFieldChanged(column, s.toString()); } }); mFields.addView(fieldView); } }
首先调用了父类的setValues()方法,在父类的setValues()方法中对一些UI赋值,如Spinner mLabel,给他设置了一个Adapter,值就是kind.typeList中包含的内容,前文中提到过。
我们继续看TextFieldsEditorView的setValues()方法,有个for循环,将kind.fieldList中所有的field取出来,并创建一个对应的EditText fieldView,然后添加到mFields,mFields = (ViewGroup) findViewById(R.id.editors),来自text_fields_editor_view.xml --> edit_field_list_with_anchor_view.xml,如下:
<LinearLayout android:layout_width="0dip" android:layout_height="wrap_content" android:layout_weight="1" android:orientation="vertical"> <LinearLayout android:id="@+id/editors" android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical" android:focusable="true" android:focusableInTouchMode="true" android:descendantFocusability="afterDescendants" /> <View android:id="@+id/anchor_view" android:layout_width="match_parent" android:layout_height="0px" /> </LinearLayout>
说白了,editors这个id对应的View就是用来添加一个EditText。
稍微总结一下:
最重要的是RawContactCommonEditorView类setState()方法,其中的for循环,作用就是将账户中的每一个kind取出来,然后生成一个KindSectionView,并显示出来。而每一个KindSectionView里面,又有可能包含多个field,这取决于kind中fieldlist中添加的EditField的个数,如下图,就包含2个EditField。
至此,Phone UI的显示部分完成,具体的细节还得要仔细看代码,比如Spinner的点击事件,叉的点击事件,文中有提到,但是具体的还得研究代码,很简单,至于EditText添加的TextChangedListener的作用,这个设计到Save contact,我们先记住每个EditText都有一个TextChangedListener就好,到分析Save Contact流程时再说。
6. 添加Name UI
前面提到Name UI,我们这里仔细分析它。
在raw_contact_editor_view.xml中,有专门添加Name相关UI的布局:
<include android:id="@+id/edit_name" layout="@layout/structured_name_editor_view" />
进入structured_name_editor_view.xml:
<com.android.contacts.editor.StructuredNameEditorView xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content" android:minHeight="@dimen/editor_min_line_item_height" android:orientation="vertical"> <include layout="@layout/edit_spinner" android:layout_width="@dimen/editor_type_label_width" android:layout_height="@dimen/editor_min_line_item_height" android:layout_gravity="top" android:visibility="gone" /> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal" android:clickable="true"> <include layout="@layout/edit_field_list_with_anchor_view"/> <include android:id="@+id/expansion_view_container" layout="@layout/edit_expansion_view" android:visibility="gone" /> <include android:id="@+id/delete_button_container" layout="@layout/edit_delete_button" android:visibility="gone" /> </LinearLayout> </com.android.contacts.editor.StructuredNameEditorView>
发现这个文件和text_fields_editor_view.xml很像,当然了,看StructuredNameEditorView类的继承图,发现StructuredNameEditorView继承自TextFieldsEditorView,所以啊,他的逻辑其实也在TextFieldsEditorView里面,和Phone一样,只不过因为StructedName比较特殊,比如没有前面的Title, 后面的“Add new”和Spinner等。我以前做这块的UI定制的时候,需要改变页面中所有的EditText的效果,尤其是有多个EditText,比如Name, Address展开后的效果,其实改动还是在TextFieldsEditorView的setValues()方法中,对EditText设置背景,以及其他属性,来达到定制的需求。
相关文章推荐
- Android Phonebook编写联系人UI加载及联系人保存流程(三)
- Android Phonebook编写联系人UI加载及联系人保存流程(二)
- Android Phonebook编写联系人UI加载及联系人保存流程(一)
- Android Phonebook编写联系人UI加载及联系人保存流程(五)
- Android Phonebook编写联系人UI加载及联系人保存流程(六)
- Android UI绘制流程(一)----布局的加载
- Android 使用Loader加载联系人
- Android 图片的加载与保存
- android N Navigationbar加载流程分析
- Android UI-开源框架ImageLoader完美使用+listview加载网络图片与下载
- android UI进阶之实现listview的下拉加载
- Android下PreferenceScreen 加载流程
- 编写android加载图片的程序时,遇到了内存泄露问题!
- android FragmentTabHost切换Fragment时避免UI重新加载
- android系统联系人查询流程
- Android UI--自定义ListView(实现下拉刷新+加载更多)
- Android UI 常用项目总结------/*自己编写*/
- android UI进阶之实现listview的分页加载 推荐
- Android EGL OpenGL库说明和加载流程
- Android 7.0 插卡后APN信息的加载流程、UI界面编辑APN的流程及Android中APN配置相关的漏洞