Android开发技巧——自定义控件之自定义属性
掌握自定义控件是很重要的,因为通过自定义控件,能够:解决UI问题,优化布局性能,简化布局代码。
上一篇讲了如何通过xml把几个控件组织起来,并继承某个ViewGroup子类,把它们封装起来使用。这是我们接触到的最简单的一种自定制控件了。但许多时候,我们还需要在布局文件中使用它们的时候,能通过属性传入一些值,来影响最终的显示结果。
我们在做项目中经常会遇到的一个情况:一张图片加一个文本的组合。比如充值账户成功之后显示的一个界面,上面是一个表示成功的图标,下面是对应的说明文字:“充值成功”。或者是在登录界面的账户输入框中,输入框的左边需要显示一个表示账户的图标。如下所示:
图标文字组合的笨重实现
一开始对于这样的情况,我们可能会采用ImageView
加TextView
的方式。后来通过lint工具的提示,或者是其他的方式,你可能会知道TextView的几个属性drawableLeft
,drawableRight
,drawableTop
以及drawableBottom
可以做到。但是使用的时候,你会发现这几个属性设置进去的图片,是按其本身大小来显示的。
好像也没关系,让设计师切好图就是了。但是心里却是没底的。因为Android手机万万种,你公司的测试机却只有那两三个,也许换上某个大屏低分辨率的千元机,图标就被撑大了。所以你还是希望能设定图片的大小。
使用一个TextView实现
设定一个TextView
的drawable大小,可以通过在java代码中调用drawable的setBounds(int left, int top, int right, int bottom)
方法设置它的界限,然后调用setCompoundDrawables(Drawable left, Drawable top, Drawable right, Drawable bottom)
方法把我们的drawable对象设置进去。
但是每次调用都要设置未免太麻烦,所以我们可以继承TextView
写一个DrawableTextView
,重写setCompoundDrawablesWithIntrinsicBounds(Drawable left, Drawable top, Drawable right, Drawable bottom)
方法;或者是setCompoundDrawablesRelativeWithIntrinsicBounds(Drawable start, Drawable top, Drawable end, Drawable bottom)
,如果你是通过drawableStart
及drawableEnd
属性来设置图片的话。通过在这里对drawable进行setBounds()
,也一样能达到上面的效果。
现在我们用一个TextView实现了上面TextView+ImageView
的效果,达到了我们的目的:优化布局性能,简化布局代码。
但是对于这样的控件,我们可能在项目的多个地方用到,或者在其他项目也会用到。所以希望能把它做到更通用。这时我们就不能写死drawable的宽和高,而是希望能够在外部xml使用它时进行控制,也就是——自定义属性。
自定义属性
首先在res/values/attrs.xml
文件中(如果没有请创建)定义一个declare-styleable
,然后在里面定义两个属性,分别表示drawable的宽和高:
<