属性,样式,主题以及实践(attr, style, theme)(未完)

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的。我们可以这样定义。


    

和前面对比,是不是觉得在下定义就属于某一view,在下定义就不属于某一view?

其实不是这样的,属性是有一个全局空间的,无论是在下,还是在下定义的都属于这个全局空间,比如说,对于以上两种情况定义的属性,我们可以这样R.attrs.customattrR.attrs.showText来引用,可见与其是否在没有关系。

既然属性都在一个全局空间中,那么就不允许同名不同类型的属性定义,如以下是错误的。


    
    

好,到这里,是不是有了很多疑问。如

  1. 什么情况下属性要定义在下,什么情况下不需要
  2. 及其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是由生成的,而PieChart就是对应的name属性。所以说的name可以是任意值,只要在obtainStyledAttributes传入相应的R.styleable.xxx就行了,但是无意义的值将造成代码的难读。

同时,从以上代码也可知道起的作用主要是为了方便将一组属性组织到一起,方便在view的构造函数中获得其属性值。

至于第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