0. 前言
最近写Android app时要美化外观了,但是发现自己对attr,style,theme这几个概念理解的比较模糊,不知道哪些应该定义在styles.xml中,哪些应该定义在theme中,从而不知道好的实践是什么,因此也写不出清晰,分离的代码。
Google了一些资源,现总结如下。
1. 属性,样式,主题(attr, style, theme)
attr
每种View都有属性,不管是自定义view,还是内置的view, 都要定义一些属性,对于自定义的view,官方文档中说明定义属性的方法。
在项目的attrs.xml文件中,添加
其中一个良好的规范是declare-styleable的name一般定义为View的名字,但既然是规范而不是必须就说明也可以不这样,至于为什么,下文会讲到。
对于内置的view,其实和自定义view也一样,只不过Google已经帮你定义好了。那么其属性的定义必定也是类似于以上这种形式。
那么相关的代码在哪里呢?
就在SDK下的attrs.xml中,在这个文件中搜索view的名称就能找到可用的属性了(当然也可在官方文档中找到其支持的属性)
还有一个关键的地方,以上的讲解给人一种属性必定属于某一view的印象,其实属性是可以不属于任何view的。我们可以这样定义。
和前面对比,是不是觉得在
其实不是这样的,属性是有一个全局空间的,无论是在R.attrs.customattr
和R.attrs.showText
来引用,可见与其是否在
既然属性都在一个全局空间中,那么就不允许同名不同类型的属性定义,如以下是错误的。
好,到这里,是不是有了很多疑问。如
- 什么情况下属性要定义在
下,什么情况下不需要 及其name值是做什么用的?为什么在其下定义属性就和view关联上了?
先说第二个问题。
要想理解第二个问题,关键的一个地方是理解obtainStyledAttributes
函数。而该函数一般是在view的构造函数中调用的。继续来看官方文档中的例子。
public PieChart(Context context, AttributeSet attrs) {
super(context, attrs);
TypedArray a = context.getTheme().obtainStyledAttributes(
attrs,
R.styleable.PieChart,
0, 0);
try {
mShowText = a.getBoolean(R.styleable.PieChart_showText, false);
mTextPos = a.getInteger(R.styleable.PieChart_labelPosition, 0);
} finally {
a.recycle();
}
}
注意obtainStyledAttributes
的参数R.styleable.PieChart
,R说明是一个资源,styleable是资源类型,PieChart是资源的名称,
styleable是由
同时,从以上代码也可知道
至于第1个问题,在主题一节会讲到。
style
前面已经说到如何定义属性,但是属性要有值啊,属性的值在哪里指定的呢?
最简单的方法在Layout文件中定义,像这样:
但是这样不太好,我们知道CSS就是将外观样式从HTML中分离出来,同样的思想用到这里,可以这样。
从上可以看出,样式为就是为属性进行赋值。
现在来谈一谈内置view的样式。
我们平时使用一个Button,一个TextView,一个ImageView,很多属性值并没有指定,但依然可以显示出某种样式,既然有样式就一定是为相应属性赋值了,那么在哪里呢?
定义的地方在SDK的styles.xml中,该文件中定义了很多style,其名称表明了style的样式,这也是一个好的命令规范。
其实,影响一个view的style并非只有这一个文件,我们知道,影响一个界面外观的还有一个因素,那就是主题因素。至于主题和样式的关系,以及两者是如何影响到一个view的外观的,在讲解了主题之后,通过分析一个view的源码来说明这个问题。
theme
Android系统已经内置了很多主题,这些主题的定义是在SDK的themes.xml文件中,打开该文件,内容如下
从名字中可以看出,这是一个透明的Button,如果为某个Button设为该style,则该Button就是透明的。这里只影响到一个Button。
themes.xml