深入理解Android之Attr&Style&Theme

先从是什么开始

在日常开发中,我们会经常接触到Attr、Style、Theme这三个概念,但许多小伙伴一直对它们一知半解,在深入了解之前,这里先给出它们三者的基本定义。

  • Attr:属性(Attribute),用于指定UI的某种风格样式,比如android:layout_width就是一种Attr;
  • Style:风格,一系列Attr的集合,用于为UI指定一个“复合风格样式”;
  • Theme:主题,与Style的作用一样,区别于Style的作用范围是View,而Theme的作用范围是Activity或Application。

接下来我们来逐一详细介绍Attr、Style与Theme。

Attr

Framework中的Attr

我们在平时的开发中,更多的是使用Attr,只有在自定义View时才会定义Attr。Attr的定义很简单,我们拿平常经常使用的android:layout_xxx属性来举例,看看Android Framework中是如何定义Attr的。(取自

    
            
               
                
            
        

            
                
               
            
    

从以上代码中我们可以看到,layout_xxx属性的取值范围为三个枚举值,其中使用fill_parent和match_parent是等价的,因为他们的value相同,之所以保留fill_parent,是为了兼容老版本。format表示了Attr的类型,可取的值有以下类型:

  • color:颜色值,如#000000
  • reference:引用某一资源ID。如@drawable/xxx
  • boolean:布尔值,true或false
  • dimension:尺寸值,可以为wrap_content、match_parent或是具体大小(xx dp)
  • float:浮点型
  • fraction:百分数
  • integer:整型
  • string:字符串类型
  • enum:枚举类型,各个取值互斥
  • flag:标记位,各个取值可用“|”连接

接下来,我们来看下LinearLayout的showDividers属性的定义:

    
      
      
      
  

我们可以看到,它的取值有四种。那么问题来了,enum与flag标签的区别是什么呢?正如我们上面所提到的,这两者的区别在于flag的几个取值不互斥,而enum的几个取值是互斥的。

自定义Attr

自定义Attr十分简单,只需要在res/values目录下新建一个attrs.xml,然后仿照Framework中的定义即可,这里我们定义一个名为MyStyle的属性组:



      
              
      
      
  

使用Attr

我们在布局文件中这样使用自定义Attr:


 
    

使用自定义Attr时我们要自定义一个命名空间,上例中我们自定义的命名空间为myview,com.example.customview为我们的自定义View类所在包。

获取自定义Attr

一种常见的在自定义View类中获取Attr的代码是这样的:

public MyView(Context context, AttributeSet attrs) {
  super(context, attrs);
  TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.MyStyle);
  String name = ta.getString(R.styleable.MyStyle_myName, "absfree");
   . . .
} 

而上面代码中的obtainStyledAttributes方法最终调用的是以下重载版本的方法:

public final TypedArray obtainStyledAttributes (AttributeSet set, int[] attrs, 
    int defStyleAttr, int defStyleRes)

我们来解释以下这个方法四个参数的含义:

  • set:属性集,会传入到自定义View的构造器中,它保存了布局文件中为View指定的所有属性
  • attrs:想要获取的属性
  • defStyleAttr:表示一个指向Style的类型为reference的Attr
  • defStyleRes:表示Style的资源ID

后两个参数都用于指定默认Style,当从attrs中找不到我们想要获取的属性时,就会使用默认Style,其中defStyleAttr的优先级高于defStyleRes。

Style

自定义Style

在res/values/styles.xml的标签内增加如下内容:


如此一来,我们便定义了一个名为MyStyle的Style,接下来我们看看如何使用它。

使用自定义Style

使用自定义Style与使用自定义Attr相仿:


如此一来,在MyView类中,我们便可以通过Theme的obtainStyledAttributes获取到自定义Style的值。比如以下代码可以后去到MyStyle中的myName的值。

final Resources.Theme theme = context.getTheme();
TypedArray ta = theme.obtainStyledAttributes(attrs, R.styleable.MyStyle, 
    defStyleAttr, defStyleRes);
String name = ta.getString(R.styleable.MyStyle_myName);
ta.recycle();

这里的obtainStyledAttributes方法即为我们上面获取Attr时使用的方法。

Theme

自定义Theme

自定义Theme的方法与自定义Style相同,也使用

Style的优先级要高于Theme,如此一来我们可以先定义整个应用的整体风格样式,然后可以根据需要对局部风格样式做出个性化修改。

获取Theme中的Attr

在xml文件中获取Theme中Attr的语法如下:

?[:][/]

若是本应用中的Attr,则可以省去
比如,我们向把TextView的text指定为MyStyle中的myName,只需按如下设置:


参考资料

  1. Android自定义View属性的相关细节
  2. 深入理解Android中的自定义属性
  3. Attr、Style和Theme详解

**长按或扫描二维码关注我们,让您利用每天等地铁的时间就能学会怎样写出优质app。 **


深入理解Android之Attr&Style&Theme_第1张图片

你可能感兴趣的:(深入理解Android之Attr&Style&Theme)