Launcher源码浅析-----Launcher自定义布局属性

来源:互联网 发布:大数据交换平台 编辑:程序博客网 时间:2024/05/22 15:36

怕以后找不到,转载过来,原博为:http://blog.csdn.net/stevenhu_223/article/details/10051279

====================================================================================================================================

在上一篇文章《Launcher源码浅析-----Launcher布局》中,对Launcher的总布局文件Launcher.xml进行了分析。在分析Launcher布局文件代码过程中,会看到一些以launcher:开头而不是以android:开头的布局属性的定义。如launcher.xml文件中id为workspace的视图布局,如下代码:

[html] view plaincopy
  1. <com.android.launcher2.DragLayer  
  2.     xmlns:android="http://schemas.android.com/apk/res/android"  
  3.     xmlns:launcher="http://schemas.android.com/apk/res/com.android.launcher"  
  4.   
  5.     android:id="@+id/drag_layer"  
  6.     android:layout_width="match_parent"  
  7.     android:layout_height="match_parent">  
  8. ...  
  9.  <!-- Workspace即手机桌面,默认系统是包含可翻转5页 -->  
  10.     <com.android.launcher2.Workspace  
  11.         android:id="@+id/workspace"  
  12.         android:layout_width="match_parent"  
  13.         android:layout_height="match_parent"  
  14.         android:paddingTop="@dimen/qsb_bar_height_inset"  
  15.         android:paddingBottom="@dimen/button_bar_height"  
  16.         launcher:defaultScreen="2"  
  17.         launcher:cellCountX="4"  
  18.         launcher:cellCountY="4"  
  19.         launcher:pageSpacing="@dimen/workspace_page_spacing"  
  20.         launcher:scrollIndicatorPaddingLeft="@dimen/workspace_divider_padding_left"  
  21.         launcher:scrollIndicatorPaddingRight="@dimen/workspace_divider_padding_right">  
  22.   
  23.         <!-- Workspace总共可翻转5个页面,一个 workspace_screen定义一个页面布局-->  
  24.         <include android:id="@+id/cell1" layout="@layout/workspace_screen" />  
  25.         <include android:id="@+id/cell2" layout="@layout/workspace_screen" />  
  26.         <include android:id="@+id/cell3" layout="@layout/workspace_screen" />  
  27.         <include android:id="@+id/cell4" layout="@layout/workspace_screen" />  
  28.         <include android:id="@+id/cell5" layout="@layout/workspace_screen" />  
  29.     </com.android.launcher2.Workspace>  
  30. ...  
  31. </com.android.launcher2.DragLayer>  

    从上面的代码中,可以知道,布局属性defaultScreen、cellCountX、cellCountY、pageSpacing、scrollIndicatorPaddingLeft、scrollIndicatorPaddingRight都是以launcher:开头的,而不是android:开头(android:开头是android系统中固有的布局属性)。android和launcher分别是属性的命名空间,在xml文件的根元素中定义,如:xmlns:android="http://schemas.android.com/apk/res/android"和xmlns:launcher="http://schemas.android.com/apk/res/com.android.launcher"。其中"http://schemas.android.com/apk/res/是固定的,后面的android和com.android.launcher的分别为对应的包名。com.android.launcher就是Launcher的包名。

      也就是说,以launcher:开头的是Launcher系统应用中自己声明和定义的属性,那么这些属性是如何声明、定义以及在代码中利用的呢?接下来还是以id为workspace的视图布局为例进行说明。

    --> id为workspace的视图布局对应的是自定义视图类Workspace,Workspace类的代码如下:

[java] view plaincopy
  1. public class Workspace extends SmoothPagedView  
  2.         implements DropTarget, DragSource, DragScroller, View.OnTouchListener,  
  3.         DragController.DragListener {  
  4. ...  
  5.     private int mDefaultPage;  
  6.     //一页面默认x轴和y轴方向上的细胞晶格数目(4x4)  
  7.     private static final int DEFAULT_CELL_COUNT_X = 4;  
  8.     private static final int DEFAULT_CELL_COUNT_Y = 4;  
  9. ...  
  10.  public Workspace(Context context, AttributeSet attrs, int defStyle) {  
  11.         super(context, attrs, defStyle);  
  12.     ...   
  13.         int cellCountX = DEFAULT_CELL_COUNT_X;  
  14.         int cellCountY = DEFAULT_CELL_COUNT_Y;  
  15.   
  16.         TypedArray a = context.obtainStyledAttributes(attrs,  
  17.                 R.styleable.Workspace, defStyle, 0);  
  18.     ...  
  19.         cellCountX = a.getInt(R.styleable.Workspace_cellCountX, cellCountX);  
  20.         cellCountY = a.getInt(R.styleable.Workspace_cellCountY, cellCountY);  
  21.         mDefaultPage = a.getInt(R.styleable.Workspace_defaultScreen, 1);  
  22.         a.recycle();  
  23.     ...  
  24.         }  
  25. ...  
  26. }  
    Workspace的构造函数中,可以知道,TypedArray对象a是通过调用Workspace构造函数第一个参数context的obtainStyledAttributes方法创建的,obtainStyledAttributes方法的第一个参数是Workspace构造函数的第二个参数attrs(AttributeSet)对象。重点是obtainStyledAttributes的第二个参数R.styleable.Workspace,R.styleable.Workspace对应的是一个int[]数组(资源id数组)。而这种以R.styleable.xxx一般是在attrs.xml文件中声明的。

     -->为此,跟踪到Launcher中的attrs.xml文件(该文件所在路径为packages/apps/Launcher2/res/values/attrs.xml),该文件中有如下代码:

[html] view plaincopy
  1. <resources>  
  2. ...  
  3.     <declare-styleable name="Workspace">  
  4.         <!-- The first screen the workspace should display. -->  
  5.         <attr name="defaultScreen" format="integer"  />  
  6.         <!-- The number of horizontal cells in the CellLayout -->  
  7.         <attr name="cellCountX" format="integer"  />  
  8.         <!-- The number of vertical cells in the CellLayout -->  
  9.         <attr name="cellCountY" format="integer"  />  
  10.     </declare-styleable>  
  11. ...  
  12. </resources>  
    从attrs.xml代码中,可以知道,name="Workspace"的declare-styleable元素数组下分别有子元素defaultScreen、cellCountX、cellCountY,它们均为Launcher中自定义的布局属性名称,attrs.xml文件中的代码就是对Launcher自定义布局属性的声明,format=“xxx”即为布局属性的数据类型,这里的defaultScreen、cellCountX、cellCountY等自定义属性均为integer类型。

    -->回到上文提到的Workspace的构造函数中的代码:

[java] view plaincopy
  1. TypedArray a = context.obtainStyledAttributes(attrs,  
  2.         R.styleable.Workspace, defStyle, 0);  
        所以,obtainStyledAttributes方法的第二个参数R.styleable.Workspace对应的是attrs.xml文件中声明的属性资源数组<declare-styleable name="Workspace">;

    -->通过R.styleable.Workspace创建TypedArray对象a后,就可以调用a的getxxx函数取得在属性资源数组Workspace中声明的各个布局属性的值了,如下:

[java] view plaincopy
  1. cellCountX = a.getInt(R.styleable.Workspace_cellCountX, cellCountX);  
  2. cellCountY = a.getInt(R.styleable.Workspace_cellCountY, cellCountY);  
  3. mDefaultPage = a.getInt(R.styleable.Workspace_defaultScreen, 1);  
     R.styleable.Workspace_cellCountX表示Workspace资源数组中声明的cellCountX布局属性,只要为Workspace中的声明的布局属性,均用Workspace+下划线+布局属性表示。

    a.getInt(R.styleable.Workspace_cellCountX, cellCountX)方法首先会获取布局属性cellCountX定义的值,若该属性的值没有定义,则取第二个参数cellCountX的值作为默认值;在Workspace的构造函数中,cellCountX被赋值为DEFAULT_CELL_COUNT_X,而DEFAULT_CELL_COUNT_X被初始化为4(即workspace的X轴方向上可放置4个快捷图标)。

    -->布局属性的值一般都是在布局文件中定义的,如Workspace的构造函数中加载的布局属性defaultScreen、cellCountX、cellCountY的值,在id为workspace的布局代码中定义如下:

[html] view plaincopy
  1. <com.android.launcher2.Workspace  
  2.       ...  
  3.       launcher:defaultScreen="2"  
  4.       launcher:cellCountX="4"  
  5.       launcher:cellCountY="4"  
  6.       ...  
  7. </com.android.launcher2.Workspace>  
      有一个问题值得注意:在Workspace的构造函数中加载了defaultScreen、cellCountX、cellCountY自定义属性。但是,id为workspace的视图布局代码中还有pageSpacing、scrollIndicatorPaddingLeft、scrollIndicatorPadding等自定义的布局属性,这些属性并没有在Workspace的构造函数中加载,而是通过PagedView的构造函数来加载;Workspace继承自SmoothPagedView,SmoothPagedView继承自PagedView。也就是说,PagedView为Workspace的父类。所以pageSpacing、scrollIndicatorPaddingLeft、scrollIndicatorPadding这些父类中加载的属性作为Workspace的属性也是理所当然的了。

    -->PagedView的构造函数代码如下:

[java] view plaincopy
  1. //实现翻页操作的抽象父类,有翻页效果的类都需要继承自它;  
  2. public abstract class PagedView extends ViewGroup {  
  3. ...  
  4.     public PagedView(Context context, AttributeSet attrs, int defStyle) {  
  5.     ...  
  6.         TypedArray a = context.obtainStyledAttributes(attrs,  
  7.                 R.styleable.PagedView, defStyle, 0);  
  8.         mPageSpacing = a.getDimensionPixelSize(R.styleable.PagedView_pageSpacing, 0);  
  9.         mPageLayoutPaddingTop = a.getDimensionPixelSize(  
  10.                 R.styleable.PagedView_pageLayoutPaddingTop, 0);  
  11.         mPageLayoutPaddingBottom = a.getDimensionPixelSize(  
  12.                 R.styleable.PagedView_pageLayoutPaddingBottom, 0);  
  13.         mPageLayoutPaddingLeft = a.getDimensionPixelSize(  
  14.                 R.styleable.PagedView_pageLayoutPaddingLeft, 0);  
  15.         mPageLayoutPaddingRight = a.getDimensionPixelSize(  
  16.                 R.styleable.PagedView_pageLayoutPaddingRight, 0);  
  17.         mPageLayoutWidthGap = a.getDimensionPixelSize(  
  18.                 R.styleable.PagedView_pageLayoutWidthGap, 0);  
  19.         mPageLayoutHeightGap = a.getDimensionPixelSize(  
  20.                 R.styleable.PagedView_pageLayoutHeightGap, 0);  
  21.         mScrollIndicatorPaddingLeft =  
  22.             a.getDimensionPixelSize(R.styleable.PagedView_scrollIndicatorPaddingLeft, 0);  
  23.         mScrollIndicatorPaddingRight =  
  24.             a.getDimensionPixelSize(R.styleable.PagedView_scrollIndicatorPaddingRight, 0);  
  25.         a.recycle();  
  26.     ...  
  27.     }  
  28. ...  
  29. }  
    -->同样地,我们到attrs.xml文件代码中找到R.styleable.PagedView对应的资源数组声明如下:

[html] view plaincopy
  1. <resources>  
  2. ...  
  3. <!-- PagedView specific attributes. These attributes are used to customize  
  4.          a PagedView view in XML files. -->  
  5.     <declare-styleable name="PagedView">  
  6.         <!-- The number of horizontal cells in a page -->  
  7.         <attr name="cellCountX" />  
  8.         <!-- The number of vertical cells in a page -->  
  9.         <attr name="cellCountY" />  
  10.         <!-- A spacing override for the icons within a page -->  
  11.         <attr name="pageLayoutWidthGap" format="dimension" />  
  12.         <attr name="pageLayoutHeightGap" format="dimension" />  
  13.         <!-- The padding of the pages that are dynamically created per page -->  
  14.         <attr name="pageLayoutPaddingTop" format="dimension" />  
  15.         <attr name="pageLayoutPaddingBottom" format="dimension" />  
  16.         <attr name="pageLayoutPaddingLeft" format="dimension" />  
  17.         <attr name="pageLayoutPaddingRight" format="dimension" />  
  18.         <!-- The space between adjacent pages of the PagedView. -->  
  19.         <attr name="pageSpacing" format="dimension" />  
  20.         <!-- The padding for the scroll indicator area -->  
  21.         <attr name="scrollIndicatorPaddingLeft" format="dimension" />  
  22.         <attr name="scrollIndicatorPaddingRight" format="dimension" />  
  23.     </declare-styleable>  
  24. ...  
  25. </resources>  
     format="dimension"表示属性的值是在dimens.xml定义;所以,workspace布局文件中的其他自定义属性pageSpacing、scrollIndicatorPaddingLeft、scrollIndicatorPadding是这样通过attrs.xml文件声明和PagedView的构造函数加载出来的。
     至于其他的Launcher自定义的布局属性,同样的也是通过在attrs.xml文件声明、布局文件中定义、自定义视图类的构造函数中加载这几个流程。

0 0