android 自定义view参数,android自定义view中一些参数的含义

66b52468c121889b900d4956032f1009.png

8种机械键盘轴体对比

本人程序员,要买一个写代码的键盘,请问红轴和茶轴怎么选?

TL;DR

不要理会View(Context, AttributeSet, defStyleAttr)和View(Context, AttributeSet, defStyleAttr, defStyleRes), 关心View(Context), View(Context, AttributeSet), 范例代码:1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20class extends SomeView{

public (Context context){

super(context);

init(context, null, 0);

}

public (Context context, AttributeSet attrs){

super(context,attrs);

init(context, attrs, 0);

}

public (Context context, AttributeSet attrs, int defStyle){

super(context, attrs, defStyle);

init(context, attrs, defStyle);

}

private void init(Context context, AttributeSet attrs, int defStyle){

}

}

AttributeSet

这个参数代表了所有在 XML 中申明的属性, 例如:1

2

3

4

5

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:text="@string/hello"

undeclaredAttr="value for undeclared attr" />

所有 XML 中调用都会涉及 View 的两个参数的构造函数, 此时 AttributeSet 就会包含四个属性: layout_width, layout_height, text, undeclaredAttr

可能有的人会好奇这些属性是从哪里来的,实际上在自定义 View 时,我们可以在 attrs 中声明declare-styleable来为我们的 View 增加属性, 例如:1

2

3

4

5

6

7

上面这个就是 ImageView 中 src 属性的由来, 有了这个定义, Android 的 ImageView 才能通过 xml 来设置 src 属性

通常在View(Context context, AttributeSet attrs), 我们会使用Theme.obtainStyledAttributes(android.util.AttributeSet, int[], int, int)来获取 AttributeSet 中的属性, 主要原因是因为我们往往需要依赖一套机制来解决在 xml 配置时使用的各种关系For example, if you define [email protected]/MyStyle in your XML, this method resolves MyStyle and adds its attributes to the mix. In the end, obtainStyledAttributes() returns a TypedArray which you can use to access the attributes.

defStyleAttr

View 的构造函数有一种方法签名: View(Context context, AttributeSet attrs, int defStyleAttr), 其中的 defStyleAttr 是什么含义呢?

defStyleAttr 可以理解为是你的 View 的默认风格,例如,你希望你 app 中的所有 MaterialButton 最小高度都为 72dp,那么你可以在你 app 中的 style.xml 中声明:1

2

3

4

5

6

7

8

9

...

@style/BigButton

72dp

这里 MaterialButton 构造时使用的 defStyleAttr 即R.attr.materialButtonStyle, 我们在Theme.Demo的 style 配置中定义了我们自己的materialButtonStyle, 因此 App 内所有用的 MaterialButton 最小高度就是 72dp 了

实际上在上一个 Part 中我们提到Theme.obtainStyledAttributes(android.util.AttributeSet, int[], int, int)时会发现其第三个参数名也是 defStyleAttr, 这里的defStyleAttr和我们在 View 的构造函数里面表达的是同一个意思. 这里举个例子方便大家理解, 以 Android 的 TextView 举例:

首先我们需要声明一下我们 TextView 支持的属性:1

2

3

4

5

6

7

8

9

10

11

12

这里的 textViewStyle 被我们声明为 reference, 即 textViewStyle 可以被定义为某一种 style

接着我们声明一下我们的 style1

2

3

4

5

6

7

8

9

10

11

12

@style/Widget.TextView

在 Manifest 中我们声明使用此 style1

2

3

4

android:name=".MyActivity"

android:theme="@style/Theme"

/>

接着在 TextView 构造时我们调用:1TypedArray ta = theme.obtainStyledAttributes(attrs, R.styleable.TextView, R.attr.textViewStyle, 0);

此时会产生如下的结果:任何在 xml 中显式定义的属性会优先返回

如果 xml 中没有定义的属性, 那么会从R.styleable.TextView指向的 style, 在这里即@style/Widget.TextView, 取出

defStyleRes

View 的构造函数中还有最后一种: View(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes), 其中的 defStyleRes 又是什么意思呢?

简单来说, 当 defStyleAttr 为 0 或者没有在当前主题中设置 defStyleAttr 时, 就会使用 defStyleRes 对应的 style 来构造这个 View

小结

列举一下在不同位置设置的属性使用的优先级,简单来说优先级从高到低如下排列:1. Any value defined in the AttributeSet.

2. The style resource defined in the AttributeSet (i.e. [email protected]/blah).

3. The default style attribute specified by defStyleAttr.

4. The default style resource specified by defStyleResource (if there was no defStyleAttr).

5. Values in the theme.

P.S 为什么不使用集联方式实现自定义 View

这里有一点需要注意, 往往我们会采用如下方式实现自定义 View:1

2

3

4

5

6

7

8

9

10

11

12

13

14class extends SomeView{

public MyView(Context context){

this(context, null);

}

public MyView(Context context, AttributeSet attrs){

this(context,attrs, 0);

}

public MyView(Context context, AttributeSet attrs, int defStyle){

super(context, attrs, defStyle);

}

}

这种写法被称为telescopic constructor

但这样写有可能会丢掉继承自 SomeView 的默认风格配置, 因为很有可能 SomeView 就是用集联方式实现构造的, 例如:1

2

3

4

5

6

7

8

9

10

11

12public SomeView(Context context){

this(context, null);

}

public SomeView(Context context, @Nullable AttributeSet attrs){

this(context, attrs, com.android.internal.R.attr.textViewStyle);

}

public SomeView(Context context, @Nullable AttributeSet attrs, int defStyleAttr){

this(context, attrs, defStyleAttr, 0);

}

如果你在MyView(Context)中没有调用super(context), 那么你就会丢掉com.android.internal.R.attr.textViewStyle的所有默认属性值, 会给你造成一些麻烦, 因此建议参考TL;DR中的方式实现自定义 View 的构造

References

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值