2014-01-0710:23:22将百度空间里的东西移过来。

5.KindSectionView

KindSectionView是何方神圣呢?它又是怎么怎么和一个DataKind,以及一个RawContactDelta绑定到一起的呢?继续看,进入KindSectionView,其实KindSectionView就是一个普通的自定义View,他的作用还真的就是将DataKind中包含的数据变成UI显示出来,那么这个View是什么呢?它有自己的xml文件:item_kind_section.xml:

 1 <com.android.contacts.editor.KindSectionView 2     xmlns:android="http://schemas.android.com/apk/res/android" 3     android:layout_width="match_parent" 4     android:layout_height="wrap_content" 5     android:layout_marginBottom="@dimen/raw_contact_sect_fields_margin_bottom" 6     android:orientation="vertical"> 7     8     <include 9         android:id="@+id/kind_title_layout"10         layout="@layout/edit_kind_title" />11    12     <LinearLayout13         android:id="@+id/kind_editors"14         android:layout_width="match_parent"15         android:layout_height="wrap_content"16         android:orientation="vertical" />17    18     <Button19         android:id="@+id/add_text"20         android:layout_width="wrap_content"21         android:layout_height="wrap_content"22         android:layout_gravity="start"23         android:text="@string/add_new_entry_for_section"24         android:drawableStart="@drawable/spb_plus_icn" />25    26 </com.android.contacts.editor.KindSectionView>

对照这图片我们分析:

kind_title_layout:就是上图中的Phone那个View;

add_text:就是上图中的“Add new” Button;

kind_editors:就是介于这两者之间的部分。当然,对add_text的点击事件处理也在KindSectionView类,如下:

 1 @Override 2 protected void onFinishInflate() { 3     setDrawingCacheEnabled(true); 4     setAlwaysDrawnWithCacheEnabled(true); 5     6     mInflater = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE); 7     8     mTitle = (TextView) findViewById(R.id.kind_title); 9     mEditors = (ViewGroup) findViewById(R.id.kind_editors);10     mAddFieldFooter = findViewById(R.id.add_text);11     mAddFieldFooter.setOnClickListener(new OnClickListener() {12         @Override13         public void onClick(View v) {14             mAddFieldFooter.setVisibility(View.GONE);15             addItem();16         }17     });18     super.onFinishInflate();19 }

不过我们还是继续沿着KindSectionView类setState()方法往下分析,rebuildFromState()-->createEditorView(),createEditorView()方法具体加载了每一个DataKind,代码如下:

 1 private View createEditorView(ValuesDelta entry) { 2     final View view; 3     try { 4         view = mInflater.inflate(mKind.editorLayoutResourceId, mEditors, false); 5     } catch (Exception e) { 6     } 7     8     view.setEnabled(isEnabled()); 9    10     if (view instanceof Editor) {11         Editor editor = (Editor) view;12         editor.setDeletable(true);13         editor.setValues(mKind, entry, mState, mReadOnly, mViewIdGenerator);14         editor.setEditorListener(this);15     }16     mEditors.addView(view);17     return view;18 }

首先是mKind,这个值就是section.setState(kind, state,false, vig)传过来的,它先取出editorLayoutResourceId,然后解析为View,并绑定在mEditors上,然后再操作,那么editorLayoutResourceId是什么?我们回过头去看DataKind:

 1 public DataKind() { 2     editorLayoutResourceId = R.layout.text_fields_editor_view; 3     maxLinesForDisplay = 1; 4 } 5     6 public DataKind(String mimeType, int titleRes, int weight, boolean editable, 7         int editorLayoutResourceId) { 8     this.mimeType = mimeType; 9     this.titleRes = titleRes;10     this.weight = weight;11     this.editable = editable;12     this.typeOverallMax = -1;13     this.editorLayoutResourceId = editorLayoutResourceId;14     maxLinesForDisplay = 1;15 }

DataKind有两个默认的构造器,无参构造器设置了默认的text_fields_editor_view,以LocalAccountType为例:

1 protected DataKind addDataKindStructuredName(2     Context context) throws DefinitionException {3     DataKind kind = addKind(new DataKind(StructuredName.CONTENT_ITEM_TYPE,4             R.string.nameLabelsGroup, -1, true,5             R.layout.structured_name_editor_view));

添加Name时,使用R.layout.structured_name_editor_view:

1 protected DataKind addDataKindNickname(2     Context context) throws DefinitionException {3     DataKind kind = addKind(new DataKind(Nickname.CONTENT_ITEM_TYPE,4                 R.string.nicknameLabelsGroup, 115, true,5                 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:

 1 <com.android.contacts.editor.TextFieldsEditorView 2     xmlns:android="http://schemas.android.com/apk/res/android" 3     android:layout_width="match_parent" 4     android:layout_height="wrap_content" 5     android:orientation="vertical"> 6     7     <LinearLayout 8         android:layout_width="match_parent" 9         android:layout_height="wrap_content"10         android:layout_weight="1"11         android:orientation="horizontal"12         android:gravity="center_vertical"13         android:focusable="true"14         android:clickable="true">15    16         <include17             layout="@layout/edit_spinner"18             android:layout_width="@dimen/editor_type_label_width"19             android:layout_height="@dimen/editor_min_line_item_height"20             android:layout_gravity="top"21             android:layout_marginEnd="@dimen/raw_contact_edit_spinner_margin_end"22             android:visibility="gone" />23    24         <include25             layout="@layout/edit_field_list_with_anchor_view" />26    27         <FrameLayout28             android:layout_width="wrap_content"29             android:layout_height="match_parent">30    31             <include32                 android:id="@+id/expansion_view_container"33                 layout="@layout/edit_expansion_view"34                 android:visibility="gone" />35    36             <include37                 android:id="@+id/delete_button_container"38                 layout="@layout/edit_delete_button"39                 android:visibility="gone" />40    41         </FrameLayout>42    43     </LinearLayout>44    45 </com.android.contacts.editor.TextFieldsEditorView>

edit_spinner:上图中“Home” Spinner;

expansion_view_container:展开或折叠Button,这个只有在Postal Address和Name中用到;

delete_button_container:上图中的叉;

TextFieldsEditorView类的继承关系如图:

我们进入TextFieldsEditorView的setValues()方法:

 1 @Override 2 public void setValues(DataKind kind, ValuesDelta entry, RawContactDelta state, boolean readOnly, ViewIdGenerator vig) { 3     super.setValues(kind, entry, state, readOnly, vig); 4     int fieldCount = kind.fieldList.size(); 5     mFieldEditTexts = new EditText[fieldCount]; 6     for (int index = 0; index < fieldCount; index++) { 7         final EditField field = kind.fieldList.get(index); 8         final EditText fieldView = createFieldView(field.column); 9         fieldView.setTextAppearance(getContext(), android.R.style.TextAppearance_Medium);10         mFieldEditTexts[index] = fieldView;11    12    13         fieldView.addTextChangedListener(new TextWatcher() {14             @Override15             public void afterTextChanged(Editable s) {16                 // Trigger event for newly changed value17                 onFieldChanged(column, s.toString());18             }19    20         });21    22         mFields.addView(fieldView);23     }24    25 }

首先调用了父类的setValues()方法,在父类的setValues()方法中对一些UI赋值,如SpinnermLabel,给他设置了一个Adapter,值就是kind.typeList中包含的内容,前文中提到过。

我们继续看TextFieldsEditorView的setValues()方法,有个for循环,将kind.fieldList中所有的field取出来,并创建一个对应的EditTextfieldView,然后添加到mFields,mFields = (ViewGroup) findViewById(R.id.editors),来自text_fields_editor_view.xml -->edit_field_list_with_anchor_view.xml,如下:

 1 <LinearLayout 2     android:layout_width="0dip" 3     android:layout_height="wrap_content" 4     android:layout_weight="1" 5     6     android:orientation="vertical"> 7     <LinearLayout 8          android:id="@+id/editors" 9          android:layout_width="match_parent"10          android:layout_height="wrap_content"11          android:orientation="vertical"12          android:focusable="true"13          android:focusableInTouchMode="true"14          android:descendantFocusability="afterDescendants" />15     <View16          android:id="@+id/anchor_view"17          android:layout_width="match_parent"18          android:layout_height="0px" />19 </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的布局:

1 <include2     android:id="@+id/edit_name"3     layout="@layout/structured_name_editor_view" />

进入structured_name_editor_view.xml:

 1 <com.android.contacts.editor.StructuredNameEditorView 2     xmlns:android="http://schemas.android.com/apk/res/android" 3     android:layout_width="match_parent" 4     android:layout_height="wrap_content" 5     android:minHeight="@dimen/editor_min_line_item_height" 6     android:orientation="vertical"> 7     8     <include 9         layout="@layout/edit_spinner"10         android:layout_width="@dimen/editor_type_label_width"11         android:layout_height="@dimen/editor_min_line_item_height"12         android:layout_gravity="top"13         android:visibility="gone" />14    15     <LinearLayout16         android:layout_width="match_parent"17         android:layout_height="wrap_content"18         android:orientation="horizontal"19         android:clickable="true">20    21         <include22             layout="@layout/edit_field_list_with_anchor_view"/>23    24         <include25             android:id="@+id/expansion_view_container"26             layout="@layout/edit_expansion_view"27             android:visibility="gone" />28    29         <include30             android:id="@+id/delete_button_container"31             layout="@layout/edit_delete_button"32             android:visibility="gone" />33     </LinearLayout>34    35 </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设置背景,以及其他属性,来达到定制的需求。

更多相关文章

  1. Android(安卓)Studio使用AIDL技术进行SDK开发
  2. 在Android(安卓)Studio中运行java main方法
  3. Android定时器Timer.schedule
  4. [Android(安卓)Studio] 关于*.SO压缩问题
  5. android动态加入xml布局并设置id
  6. Android-EventBus(手写简易版)
  7. AndroidStudio中的图片资源存放位置以及drawable文件夹的创建方
  8. Android四大组件生命周期,组件类的继承与实现,Context
  9. android,ExpandableList,将被选中的group置于顶端

随机推荐

  1. android SSL证书认证、SSL双向认证、http
  2. android TextView属性大全
  3. 图片走廊
  4. android camera系统3A模式及其状态转换(二
  5. 【Android】如何寻找出某个Intent是否可
  6. ch027 Android(安卓)Json
  7. android ContentResolver
  8. Android计算器布局
  9. android ToggleButton
  10. android slidemenu