styles, attrs, them三个资源引见

styles, attrs, them三个资源介绍

一、Styles和Themes

      在Android中,style被用来指定窗体或视图的样式,比如视图的宽高、补白(padding)、背景,字体颜色等。style不需我们在代码中进行设置,
    可以在xml文件中按照DTD格式进行配置。Android中的style其实跟css的思想一样,允许我们把功能实现和外观设计分离开,
    View配置也提供了html中如id、name属性一样的功能标签style,让我们有能力把所有的样式集中在一个地方,

    如下一个例子(main.xml)
  • <? xml version= "1.0" encoding = "utf-8"?>
    <LinearLayout xmlns:android ="http://schemas.android.com/apk/res/android"
        android:layout_width= "match_parent"
        android:layout_height= "match_parent"
        android:orientation= "vertical">
       
        <TextView
            android:id ="@+id/tv1"
            android:layout_width ="wrap_content"
            android:layout_height ="wrap_content"
            android:textColor ="#FFFFFF" />
    
        <TextView
            android:id ="@+id/tv2"
            android:layout_width ="wrap_content"
            android:layout_height ="wrap_content"
            android:textColor ="#FFFFFF" />
    
        <TextView
            android:id ="@+id/tv3"
            android:layout_width ="wrap_content"
            android:layout_height ="wrap_content"
            android:textColor ="#FFFFFF" />
       
    </LinearLayout>

    在上面的布局文件中,三个TextView的android:layout_width、android:layout_height、android:textColor样式属性都一样,
    这种情况下我们就可以单独定义一个style,以一种更好的做法来替代上面的写法,在此处可以把该style部分理解为"模板"。
    sample1_style.xml (
注:style文件必须在values-*目录中,且必须按照DTD格式来编写各个定义好的标签)
  • <resources xmlns:android ="http://schemas.android.com/apk/res/android">
        <style name= "Sample1">
            <item name= "android:layout_width">wrap_content </item>
            <item name= "android:layout_height">wrap_content </item>
            <item name= "android:textColor">#00FF00 </item >
        </style>
    </resources>

    接下来我我们对main.xml进行改造:
    (注:使用时只需使用style属性引用我们定义好的style即可,这种方式可以有效的避免做重复性的工作,简化我们的工作)
  • <? xml version= "1.0" encoding = "utf-8"?>
    < LinearLayout xmlns:android ="http://schemas.android.com/apk/res/android"
        android:layout_width= "match_parent"
        android:layout_height= "match_parent"
        android:orientation= "vertical" >
    
        <TextView
            android:id ="@+id/tv1"
            style= "@style/Sample1"
            android:text ="@string/sample1_tv1" />
    
        <TextView
            android:id ="@+id/tv2"
            style= "@style/Sample1"
            android:text ="@string/sample1_tv2" />
    
        <TextView
            android:id ="@+id/tv3"
            style= "@style/Sample1"
            android:text ="@string/sample1_tv3" />
    
    </ LinearLayout>

     Theme是应用于整个Application、Activity的style,而不是某一个View,如果style被当做Theme来应用时,
    那么整个应用或整个窗体中的元素都将使用这个风格样式(如果下面的子项不存在某一属性,那么将会被忽略),
    当然如果为某个特定的View指定了style时,相同的属性会被覆盖。使用 android:theme="@style/mystyle"来指定主题


  • <activity
                android:name=".Main"
                android:configChanges="keyboardHidden|orientation"
                android:screenOrientation="portrait"
                android:theme="@style/TitleStyle.themes">
                <intent-filter>
                    <action android:name="android.intent.action.MAIN"/>
                    <category android:name="android.intent.category.LAUNCHER"/>
                </intent-filter>
    </activity>


二、Style的继承
    Android系统为我们提供了一整套的style,比如说显示字符串最基本的style是TextAppearance,它定义了一些最基本的属性
    继承的方式有两种:(1)父Style名字.子Style名字    (2)parent="@父Style名字"  或  parent = "@style/父Style名字"
                               (3)继承android系统自带的style样式: parent = "@android:系统自带style的名字" 或
                                                                                parent = "@android:style/系统自带style的名字"
                                   <style name="TitleStyle.MyStyle" parent="@android:Theme.Light">
                                   <style name="TitleStyle.MyStyle" parent="@android:style/Theme.Light">
                                注:由2与3点可以总结出,在引用其他样式(style)时,style/可以省略。
  • <style name="TextAppearance">
    
    	<item name="android:textColor">#336699</item>
    
    	<item name="android:textSize">16sp</item>
    
    	<item name="android:textStyle">normal</item>
    
    </style>

  • 如果我们只想改变基础style中的某一项属性时,这时可以使用继承来实现
    <style name= "Sample1" parent= "@TextAppearance" >
    
        < item name= "android:textColor" >#00FF00 </item >
       
    </style >


三、属性文件attrs的作用与使用
    作用:attrs看字面意思就是一组属性的集合,那attrs有什么用呢,在自定义View的时候,一般会自定义一些属性,
             通过构造方法中AttributeSet参数的封装,让我们能够获取到为View配置的属性。

    定义attrs文件及在其他文件中引用这些属性:values/attrs.xml, values/style.xml
                1、定义单个属性: <attr name="attrsName">values</attr>
                                          eg:  <attr name="myattrs">300dp</attr>

                    在其他资源文件中引用属性设置:?attr/属性名称 
                    (注:?:表示引用属性,用这个标记,你所提供的资源名必须能够在主题属性中找到 
                                                    a、引用系统自带的attrs。eg: ?android:attrs/系统资源ID
                                          b、引用自定义的属性attrs。 eg: ?attrs/自定属性ID

                            @:下合同资源文件, eg:@string/资源ID,   @android:string/资源ID)
                                          a、在sytles.xml中使用这睦属性:
                                          <style name="MyStyles">
                                                    <item name="android:width">?attr/myattrs</item>
                                          </style>

                                  b、在<TextView>标签中使用设置的属性:
                                          <TextView android:width="?attr/myattrs" />
                                           

                2、定义一组属性的集合,这样的属性集合,一般都是在styles.xml或theme.xml中引用:
                      (1)、定义一组style属性,用<style>标签, 里面的每一项用<item>标签。(注:style属性组也可以继承)
                                  <style name="arrayAttrs">
                                         <item name="android:textColor">#000000</item>
                                         <item name="android:textSize">40sp</item>
                                  </style>

                                  在其他资源文件中,引用这一段属性组:
                                  a、在style.xml资源文件中引用,实质上是继承attrs.xml中的style属性组。
                                  <style name="myStyle" parent="arrayAttrs">  </style>  或   
                                  <style name="myStyle" parent="@style/arrayAttrs">  </style>
              
                          b、在布局中,直接引用这些属性组attrs。
                                   <TextView style="@style/arrayAttrs" />

                          c、在themes.xml资源文件中引用这些属性组,其方式与style.xml引用这些属性一样。
                                   <style name="myThemes" parent="arrayAttrs"></style>    
                                   <style name="myStyle" parent="@style/arrayAttrs">  </style>

         3、为自定义控件设置自定义属性declare-styleable,及其使用
              (1)、在attrs.xml定义自定义属性。
  •                         
    format="color | dimension | integer ........",每一种format属性,在自定义View中都有对应的get方式来获取。
    format="color" ------> getColor();
    format="dimension" -------> getDimension();
    format="integer" --------> getInteger();
    format="reference" --------> getResourceId();  //引用类型
    format="boolean" ---------> getBoolean();
    format="float" ---------> getFloat();
    format="fraction" -------> getFraction(); //百分数
    此处还有两种类型,放在后面讲枚举和标志位。

    <?xml version="1.0" encoding="utf-8"?>
    <resources xmlns:android="http://schemas.android.com/apk/res/android">
    <declare-styleable name="MyView">                    //自定属性,此处name值一般设置为自定义控件类名字相同。
    <attr name="textColor" format="color"/>          //定义字体颜色属性, 请注意format属性设置, getColor():方式取得该属性
    <attr name="textSize" format="dimension"/>     //定义字体大小属性, 请注意format属性设置, getDimension():方式取得该属性
    <attr name="backColor" format="color" />        //定义背景颜色属性, 请注意format属性设置
    </declare-styleable>
    <style name="square">   //自定义Style样式,以便其他地方引用
    <item name="android:layout_width">500px</item>
    <item name="android:layout_height">300px</item>
    </style>
    </resources>


                       (2)、自定义View控件 MyView。
                                   通过TypedArray自取自定义的declare-styleable属性组。
  • package com.fs.myselfview;

    import android.content.Context;
    import android.content.res.TypedArray;
    import android.graphics.Canvas;
    import android.graphics.Paint;
    import android.graphics.Paint.Style;
    import android.graphics.Rect;
    import android.util.AttributeSet;
    import android.view.View;
    public class MyView extends View {
     private Paint myPaint;
     private static final String myString = "Welcome to our Zoon!";
     float textSize;
     int textColor, backColor;
     public MyView(Context context) {
      super(context);
      // TODO Auto-generated constructor stub
     }
     public MyView(Context context, AttributeSet attr) { //AttributeSet:自定义属性
      super(context, attr);
      myPaint = new Paint();
      TypedArray typeArray = context.obtainStyledAttributes(attr, R.styleable.MyView);// TypedArray是一个数组容器
      textSize = typeArray.getDimension(R.styleable.MyView_textSize, 30);// 防止在XML文件里没有定义,就加上了默认值30
      textColor = typeArray.getColor(R.styleable.MyView_textColor, 0xFFFFFF);// 同上,这里的属性是:名字_属性名
      backColor = typeArray.getColor(R.styleable.MyView_backColor, 0xFFFFFF);  // 同上,这里的属性是:名字_属性名
      typeArray.recycle();                            //供以后使用。以前取回的可能就是textSize和textColor初始化的那段
     }
     @Override
     protected void onDraw(Canvas canvas) {
      super.onDraw(canvas);
      this.setBackgroundColor(backColor);
      myPaint.setTextSize(textSize);
      myPaint.setColor(textColor);
      myPaint.setStyle(Style.FILL);
      canvas.drawRect(new Rect(10, 10, 100, 100), myPaint);
      canvas.drawText(myString, 100, 100, myPaint);
     }
    }
 
                    (3)、在XML布局文件中,使用该MyView自定义组件。
  • <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:test="http://schemas.android.com/apk/res/com.fs.myselfview"  //引入名字空间
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:orientation="vertical" >

        <com.fs.myselfview.MyView
            style="@style/square"    //引用自定义的square样式
            test:backColor="#336699"
            test:textSize="40px"
            test:textColor="#996633" />

    </LinearLayout>

               4、attrs中自定义枚举类型的使用。如在定义LinearyLayout中,设置横向排列或是纵向排列时,用到了枚举。
                               (android:orientation="horizontal"
                        (1)、在<declare-styleable>中定义。
  • 基本格式:
    <declare-styleable name="名字">
            <attr name="枚举名称">
                <enum name="枚举健名" value="枚举值名" />
                <enum name="枚举 " value="枚举值名" />
            </attr>
    </declare-styleable>

    实例:
    <declare-styleable name="MyView">
            <attr name="textColor" format="color" />
            <attr name="textSize" format="dimension" />
            <attr name="backColor" format="color" />
           
            <attr name="enums">
                <enum name="zero" value="0" />
                <enum name="one" value="1" />
            </attr>
    </declare-styleable>
    (2)、 自定义View控件 MyView。通过TypedArray自取自定义的declare-styleable属性组。取得枚举是类型是通过TypeArray的getInt()函数取得。
            
    package com.fs.myselfview;

    import android.content.Context;
    import android.content.res.TypedArray;
    import android.graphics.Canvas;
    import android.graphics.Paint;
    import android.graphics.Paint.Style;
    import android.graphics.Rect;
    import android.util.AttributeSet;
    import android.view.View;
    public class MyView extends View {
     private Paint myPaint;
     private static final String myString = "Welcome to our Zoon!";
     float textSize;
     int textColor, backColor, enums;
     TypedArray typeArray;
     public MyView(Context context) {
      super(context);
      // TODO Auto-generated constructor stub
     }

     public MyView(Context context, AttributeSet attr) {
      super(context, attr);
      myPaint = new Paint();
     
      typeArray = context.obtainStyledAttributes(attr, R.styleable.myView, R.attr.enums, 0);// TypedArray是一个数组容器
      textSize = typeArray.getDimension(R.styleable.myView_textSize, 30);          // 防止在XML文件里没有定义,就加上了默认值30
      textColor = typeArray.getColor(R.styleable.myView_textColor, 0xFFFFFF);      // 同上,这里的属性是:名字_属性名
      backColor = typeArray.getColor(R.styleable.myView_backColor, 0xFFFFFF);
      enums = typeArray.getInt(R.styleable.myView_enums, 0);                       //取得attrs中定义的枚举对象
      typeArray.recycle();
     }

     @Override
     protected void onDraw(Canvas canvas) {
      super.onDraw(canvas);
      this.setBackgroundColor(backColor);
      myPaint.setTextSize(textSize);
      myPaint.setColor(textColor);
      myPaint.setStyle(Style.FILL);
      canvas.drawRect(new Rect(10, 10, 100, 100), myPaint);
      canvas.drawText(myString, 100, 100, myPaint);
     }

    }

                          (3)、在布局文件中,使用自定义的MyView控件。
  • 在下面例子中的android:orientation="horizontal"test:enums="one"是一样的。
    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:test="http://schemas.android.com/apk/res/com.fs.myselfview"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:orientation="horizontal" >
        <com.fs.myselfview.MyView
            style="@style/square"
            test:backColor="#336699"
            test:textColor="#996633"
            test:textSize="40px"
            test:enums="one" />
    </LinearLayout>
             5、标志位、位或运算在attrs中的定义和使用(在Android横坚屏切换中,会有用到)
                                
                            (1)、定义格式
  • 格式:
    <declare-styleable name="名称">  //name:一般与自定义View类的名称相同
            <attr name="flagsName">      //name:标志位名称
                <flag name="flagKey" value="flagValue" />
            </attr>
    </declare-styleable>

    实例:
    <declare-styleable name="SelfView">
            <attr name="flags">
                <flag name="stateUnspecified" value="0" />
                <flag name="stateUnchanged" value="1" />
                <flag name="stateHidden" value="2" />
                <flag name="stateAlwaysHidden" value="3" />
                <flag name="stateVisible" value="4" />
                <flag name="stateAlwaysVisible" value="5" />
                <flag name="adjustUnspecified" value="0x00" />
                <flag name="adjustResize" value="0x10" />
                <flag name="adjustPan" value="0x20" />
                <flag name="adjustNothing" value="0x30" />
            </attr>
    </declare-styleable>
                        (2)、自定义View控件SelfView。通过TypedArray自取自定义的declare-styleable属性组。取得枚举是类型是通过TypeArray的getInt()函数取得。
  • package com.fs.myselfview; 
    import android.content.Context;
    import android.content.res.TypedArray;
    import android.util.AttributeSet;
    import android.view.View;
    public class SelfView extends View {
     TypedArray typeArray;
     int flags;
     public SelfView(Context context, AttributeSet attrs) {
      super(context, attrs);
      typeArray = context.obtainStyledAttributes(attrs, R.styleable.SelfView, R.attr.flags, 0);
      flags = typeArray.getInt(R.styleable.SelfView_flags, 0);
     }
    }

                    (3)、在XML布局文件中,使用该SelfView自定义组件。
                                (在使用自定义View控件时,要引入命名空间)
  • <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:test="http://schemas.android.com/apk/res/com.fs.myselfview"   //引入命名空间
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:orientation="vertical" >

        <com.fs.myselfview.SelfView
            android:layout_width="fill_parent"
            android:layout_height="fill_parent"
            test:flags="adjustPan|stateVisible">
           
        </com.fs.myselfview.SelfView>
    </LinearLayout>