自定义属性

TypeArray 用来简化资源类型判断,declare-styleable 用来生成资源 ID 数组和对应的索引值

自定义属性的声明文件(values/attrs.xml)

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <declare-styleable name="test">
        <attr name="text" format="string" />
        <attr name="testAttr" format="integer" />
    </declare-styleable>
</resources>

自定义 View

public class MyTextView extends View {

  public MyTextView(Context context, AttributeSet attrs) {
    super(context, attrs);
    TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.test);
    String text = ta.getString(R.styleable.test_testAttr);
    int textAttr = ta.getInteger(R.styleable.test_text, -1);
    ta.recycle();
  }
}

Xml 布局文件

<RelativeLayout 
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    xmlns:zhy="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <com.example.test.MyTextView
        android:layout_width="100dp"
        android:layout_height="200dp"
        zhy:testAttr="520"
        zhy:text="@string/hello_world" />

</RelativeLayout>

代码看不懂不要紧,后面慢慢分析,我们先说一下 View 构造方法中的 AttributeSet 参数,首先AttributeSet 保存的是 View 在布局文件中声明的所有属性,而且我们的确可以通过它去获取属性键值对,下面我们修改一下 MyTextView 中的代码:

public class MyTextView extends View {
  public MyTextView(Context context, AttributeSet attrs) {
    super(context, attrs);
    int count = attrs.getAttributeCount();
    for (int i = 0; i < count; i++) {
      String attrName = attrs.getAttributeName(i);
      String attrVal = attrs.getAttributeValue(i);
      Log.e(TAG, "attrName = " + attrName + " , attrVal = " + attrVal);
    }
  }
}

运行结果为:

MyTextView(4692): attrName = layout_width , attrVal = @2131165234
MyTextView(4692): attrName = layout_height , attrVal = @2131165235
MyTextView(4692): attrName = testAttr , attrVal = 520
MyTextView(4692): attrName = text , attrVal = @2131361809

通过结果我们发现,打印出来的 text 属性是以 @ 开头的,我们改一下代码

public class CustomView extends View {
  public CustomView(Context context, @Nullable AttributeSet attrs) {
    super(context, attrs);
    if (attrs == null) return;
    int count = attrs.getAttributeCount();
    for (int i = 0; i < count; i++) {
//      if(attrs.getAttributeName(i).equals("text")) {
      if (attrs.getAttributeNameResource(i) == R.attr.text) {
        int resValue = attrs.getAttributeResourceValue(i, -1);
        if (-1 != resValue) {
          Log.e("offer", getResources().getString(resValue));
        } else {
          Log.e("offer", attrs.getAttributeValue(i));
        }
      }
    }
  }
}

在上面的例子中,我们首先通过 getAttributeResourceValue 判断资源是否是引用类型,然后再去解析对应的资源,这样就可以打印出来了,所以说 TypedArray 可以用来简化获取资源的流程

另外,我们说一下 declare-styleable 标签,该标签也是简化我们代码的,在自定义属性时,我们也可以省略该标签,我们改一下最上面的自定义属性声明文件:

自定义属性的声明文件(values/attrs.xml)

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <attr name="text" format="string" />
    <attr name="testAttr" format="integer" />
</resources>

自定义 View

public class MyTextView extends View {

  private static final int[] mAttr = { android.R.attr.text, R.attr.testAttr };
  private static final int ATTR_TEXT = 0;
  private static final int ATTR_TESTATTR = 1;

  public MyTextView(Context context, AttributeSet attrs) {
    super(context, attrs);
    TypedArray ta = context.obtainStyledAttributes(attrs, mAttr);
    String text = ta.getString(ATTR_TEXT, -1);
    int textAttr = ta.getInteger(ATTR_TESTATTR);
    ta.recycle();
  }
}

我们发现,即使没有 declare-styleable 标签,我们也可以实现自定义属性,该标签只是自动帮助我们生成了 attr 数组和对应的下标序号

另外,我们在声明自定义属性时,也可以复用系统的属性:

<declare-styleable name="test">
    <attr name="android:text" />
    <attr name="testAttr" format="integer" />
</declare-styleable>

这里我们是使用已经定义好的属性,不需要去添加 format 属性(注意声明和使用的区别,差别就是有没有 format),然后在类中这么获取:ta.getString(R.styleable.test_android_text); 布局文件中直接 android:text="@string/hello_world" 即可。说白了,属性还是系统的属性(attr 并没有增加,只是 declared-styleable 数组中多了一个值,另外多了一个下标序号而已)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

little-sparrow

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值