zoukankan      html  css  js  c++  java
  • [学习总结]8、android 自定义控件 使用declare-styleable进行配置属性(源码角度)

    declare-styleable:declare-styleable是给自定义控件添加自定义属性用的。

    官方的相关内部控件的配置属性文档:http://developer.android.com/reference/android/R.styleable.html

    起初,在自定义控件的时候,会要求构造3个方法中的一个或多个,好比我自定义的控件PersonView,

     1 public PersonView(Context context) {
     2         super(context);
     3         // TODO Auto-generated constructor stub
     4     }
     5 
     6     public PersonView(Context context, AttributeSet attrs, int defStyle) {
     7         super(context, attrs, defStyle);
     8         // TODO Auto-generated constructor stub
     9     }
    10 
    11     public PersonView(Context context, AttributeSet attrs) {
    12         super(context, attrs);
    13 }

    其中的AttributeSet attrs一般都没给它配置和使用,所以不知道这个东西到底怎么用,后来查看源码发现,这个配置在默认情况下使用的是系统自己的默认配置,一旦你直接设定了它的属性,默认属性就会被你的赋值所替代。

    下面我们拿TextView的源码看看AttributeSet是如何进行操作的。

    初始化时候,在布局文件中写android:text="拉拉";

    初始化TextView的时候,它的类中的属性都会初始化;

    接着往下看,你可以看到以下代码:

    1  TypedArray a = theme.obtainStyledAttributes(
    2                     attrs, com.android.internal.R.styleable.TextViewAppearance, defStyle, 0);
    3         TypedArray appearance = null;
    4         int ap = a.getResourceId(
    5                 com.android.internal.R.styleable.TextViewAppearance_textAppearance, -1);
    6         a.recycle();
    7         if (ap != -1) {
    8             appearance = theme.obtainStyledAttributes(
    9                     ap, com.android.internal.R.styleable.TextAppearance);

    这个就是系统在默认的资源文件R.styleable中去获取相关的配置。

    如果appearance不为空,它就会去寻找获取相关属性,接着往下看。

    此时的text = "";     就是准备输出的字符串初始化。

    之后它便会查找你布局文件XML中是否设定给了它text属性值

    之前我们设定过android:text="拉拉";  所以它便会得到相关的赋值,之后调用

    1 setText(text, bufferType);  
    2  if (hint != null) setHint(hint); 

    输出该字符串。当资源检查赋值完毕后,调用a.recycle();释放。
    同理也可以发现,像hint,textcolor这类属性都是这么初始化赋值的。

     

    思路:

    自定义控件并且自定义属性的情况下,你可以通过这样去获取判断是否配置了相关的属性,并进行赋值操作。

     

    从源码那边我们大体知道了一个控件的属性配置和初始化流程,下面就让我们按照这个思路去自己学习下如何自定义配置。

     

    下面我要写一个继承了TextView的PersonView类,给它设定属性配置,之后实现属性的显示。

    1.首先,先写attrs.xml

    在res-vlaues文件夹下创建资源文件attrs.xml或则自定义一个资源文件xx.xml,都可以。

    之后在里面配置declare-styleable ,name为PersonAttr

     1 <?xml version="1.0" encoding="utf-8"?>
     2 <resources>
     3     <declare-styleable name="PersonAttr">
     4         <attr name="name" format="reference" />
     5         <attr name="sex" format="reference" />
     6         <attr name="age" format="integer" />
     7         <attr name="weight">
     8             <flag name="fat" value="2" />
     9             <flag name="mid" value="1" />
    10             <flag name="thin" value="0" />
    11         </attr>
    12         <attr name="adult" format="boolean" />
    13         <attr name="textSize" format="dimension" />
    14     </declare-styleable>
    15 </resources>

    我这里设置了姓名name,性别sex,年龄age,以及特征属性weight(fat,mid,thin内部的3个属性及对应的属性值),还有是否成年adult,和TextView的字体大小textView。

    可能这里有人会问,format是什么,里面的单词代表的又是什么意思。

    format就是格式,里面的就是这个属性对应的格式,下面列出来大致的格式有:

    1. reference:参考某一资源ID,以此类推

    (1)属性定义:

    <declare-styleable name = "名称">

    <attr name = "background" format = "reference" />

    </declare-styleable>

    (2)属性使用:

    <ImageView

    android:layout_width = "42dip"

    android:layout_height = "42dip"

    android:background = "@drawable/图片ID"

    />

    2. color:颜色值

    <declare-styleable name = "名称">

    <attr name = "textColor" format = "color" />

    </declare-styleable>

    3. boolean:布尔值

    <declare-styleable name = "名称">

    <attr name = "focusable" format = "boolean" />

    </declare-styleable>

    4. dimension:尺寸值。注意,这里如果是dp那就会做像素转换

    <declare-styleable name = "名称">

    <attr name = "layout_width" format = "dimension" />

    </declare-styleable>

    5. float:浮点值。

    6. integer:整型值。

    7. string:字符串

    8. fraction:百分数。

    9. enum:枚举值

    10. flag:是自己定义的,类似于 android:gravity="top",就是里面对应了自己的属性值。

    11. reference|color:颜色的资源文件。

    12.reference|boolean:布尔值的资源文件

    注意://由于reference是从资源文件中获取:所以在XML文件中写这个属性的时候必须 personattr:name="@string/app_name"这种格式,否则会出错

    2.设置好属性文件后,在使用的布局中写相关配置:

     1 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
     2     xmlns:personattr="http://schemas.android.com/apk/res/com.example.declare_styleable"
     3     android:layout_width="match_parent"
     4     android:layout_height="match_parent" >
     5 
     6     <com.example.declare_styleable.PersonView
     7         android:layout_width="wrap_content"
     8         android:layout_height="wrap_content"
     9         personattr:name="@string/person_name" 
    10         personattr:weight ="fat"
    11         personattr:adult ="false"
    12         personattr:textSize="@dimen/text_size"/>
    13 
    14 </RelativeLayout>

    这里要先应用这个attr:

    1 xmlns:personattr="http://schemas.android.com/apk/res/com.example.declare_styleable"

    对应结构是:

    xmlns:你自己定义的名称="http://schemas.android.com/apk/res/你自定义的这个控件类所在的包"    (我这是com.example.declare_styleable) 

    之后在布局中自定义的类中设相关属性:

    你自己定义的名称:你设的属性 ="属性值";

    3.最后在自定义控件的构造方法中获取你配置的属性值:

     1 public class PersonView extends TextView {
     2     public PersonView(Context context) {
     3         super(context);
     4         // TODO Auto-generated constructor stub
     5     }
     6 
     7     public PersonView(Context context, AttributeSet attrs, int defStyle) {
     8         super(context, attrs, defStyle);
     9         // TODO Auto-generated constructor stub
    10     }
    11 
    12     public PersonView(Context context, AttributeSet attrs) {
    13         super(context, attrs);
    14         // TODO Auto-generated constructor stub
    15         TypedArray tArray = context.obtainStyledAttributes(attrs,R.styleable.PersonAttr);//获取配置属性
    16         String name = tArray.getString(R.styleable.PersonAttr_name);<span style="font-family: Arial, Helvetica, sans-serif;">//得到属性name</span>
    17         int age = tArray.getInt(R.styleable.PersonAttr_age, 15);
    18         Boolean adult = tArray.getBoolean(R.styleable.PersonAttr_adult, false);
    19         String str_adult = getAdultStatus(adult);
    20         int weight = tArray.getInt(R.styleable.PersonAttr_weight, 1);// 默认是中等身材,属性为:1
    21         String str_weight = getWeightStatus(weight);//获得肥胖属性
    22         float textSize = tArray.getDimension(R.styleable.PersonAttr_textSize,R.dimen.default_text_size);// 如果你设置为DP等单位,会做像素转换
    23         tArray.recycle();//回收资源
    24 //        setTextSize(textSize);//设置字体大小
    25         setText("姓名:" + name + "
    " + "年龄:" + age + "
    " + "是否成年:" + str_adult
    26                 + "
    " + "体形:" + str_weight);//给自定义的控件赋值
    27     }
    28     
    29     /** 根据传入的值判断是否成年 */
    30     public String getAdultStatus(Boolean adult ){
    31         String str_adult = "未成年";
    32         if (adult) {
    33             str_adult = "成年";
    34         }
    35         return str_adult;
    36     }
    37     
    38     /** 根据传入的值判断肥胖状态 */
    39     public String getWeightStatus(int weight){
    40         String str_weight = "中等";
    41         switch (weight) {
    42         case 0:
    43             str_weight = "瘦";
    44             break;
    45         case 1:
    46             str_weight = "中等";
    47             break;
    48         case 2:
    49             str_weight = "肥胖";
    50             break;
    51         default:
    52             break;
    53         }
    54         return str_weight;
    55     }
    56 }

    运行后就是:

    这样,以后我们就可以根据这个方法,去自定义控件并自定义配置属性了,大大提高了自定义布局的使用效率。

     

    对应的源码下载地址:下载地址

    转载地址:http://blog.csdn.net/vipzjyno1/article/details/23696537

  • 相关阅读:
    使用Skaffold一键将项目发布到Kubernetes
    线性代数回头看——线性方程组
    Python 函数 初学者笔记
    Python 用户输入&while循环 初学者笔记
    Python If&字典 初学者笔记
    Python 变量&列表 初学者笔记
    SQL 常见优化指南
    垃圾回收机制
    MySQL 前缀索引
    MySQL 常用优化
  • 原文地址:https://www.cnblogs.com/androidxiaoyang/p/3722937.html
Copyright © 2011-2022 走看看