Android样式和主题(一):简介

作者: 08_carmelo | 来源:发表于2017-05-04 20:15 被阅读258次

    前言

    样式Style和主题Theme是Android中很重要两个概念,用的时候很容易弄混淆,此篇我准备从自定义属性到自定义样式,了解一下Android里属性,样式和主题的原理。

    简介

    • Attr:属性,风格样式的最小单元;

    • Style:风格,它是一系列Attr的集合用以定义一个View的样式,比如height、width、padding等;

    • Theme:主题,它与Style作用一样,不同于Style作用于个一个单独View,而它是作用于Activity上或是整个应用。

    View的Style(样式)

    假设给自定义View:MyView设定了几个自定义属性:attr.xml

    <?xml version="1.0" encoding="utf-8"?>
    <resources>
        <declare-styleable name="dml">
            <attr name="circleColor" format="color|reference"/>
            <attr name="circleSize" format="integer"/>
        </declare-styleable>
    </resources>
    

    然后把这几个属性封装成一个Style:style.xml

    <resources>
        <style name="editStyle">
            <item name="circleColor">#343434</item>
            <item name="circleSize">40</item>
        </style>
    </resources>
    

    在布局文件中给MyView设置style:

    style="@style/editStyle"
    

    在MyView的构造方法中获取这些属性:

        public MyView(Context context, AttributeSet attrs) {
            super(context, attrs);
            TypedArray ta = context.obtainStyledAttributes(attrs,R.styleable.dml);
            int color = ta.getInt(R.styleable.dml_circleColor,-1);
            int size = ta.getInt(R.styleable.dml_circleSize,-1);
            Log.d("dml","color = " + color + "-------size = " + size);
        }
    

    看下效果:
    05-02 21:18:08.626 31441-31441/com.example.app2 D/dml: color = -13355980-------size = 40

    • 其实在Android系统中,我们给View设置属性比如TextView设置android:textSize="23sp",在TextView的源码中也是这么在构造方法中获取的,然后在OnDrawI()中绘制,这就是Android的View属性和Style的工作原理。同样,我们在Allication节点设置android:theme属性那么在Activity源码中肯定有方法来获取这个style,这就是Theme的工作原理,下面会验证。
    • 我再自定义一个View比如OtherView extends View,那么还是得在OtherView的构造方法中再次获取这些属性值,所以说Style(样式)是对View有效果。

    Activity/Application的Theme(主题)

    还是用上面自定义的两个属性,封装一个style,这次由于是用于Activity,那么需要额外的系统自带属性不然Activity不能正常工作,会崩溃

        <style name="AppEditStyle" parent="android:Theme.Material.Light">
            <item name="circleColor">#343434</item>
            <item name="circleSize">40</item>
        </style>
    

    在menifest.xml的application节点定义:

        <application
            android:name=".MyApplication"
            android:allowBackup="true"
            android:icon="@mipmap/ic_launcher"
            android:label="@string/app_name"
            android:theme="@style/AppEditStyle">
            <activity android:name=".StyleActivity">
    

    然后在Activity中获取这两个属性:

    public class StyleActivity extends Activity{
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_style);
        }
        @Override
        protected void onApplyThemeResource(Resources.Theme theme, int resid, boolean first) {
            super.onApplyThemeResource(theme, resid, first);
            TypedArray ta = theme.obtainStyledAttributes(R.styleable.dml);
            int color = ta.getInt(R.styleable.dml_circleColor,-1);
            int size = ta.getInt(R.styleable.dml_circleSize,-1);
            Log.d("dml","color = " + color + "-------size = " + size);
        }
    }
    

    看下效果:
    05-02 21:38:15.285 19755-19755/com.example.app2 D/dml: color = -13355980-------size = 40

    • 同上面的Style一样,在Android系统中我们给Applciation节点设置了Theme,那么在Activity源码中也会相应获取这个主题,然后展示出默认的Activity风格,果然在Activity源码3711行有这个回调方法:
        @Override
        protected void onApplyThemeResource(Resources.Theme theme, @StyleRes int resid,
                boolean first) {
            if (mParent == null) {
                super.onApplyThemeResource(theme, resid, first);
            } else {
                try {
                    theme.setTo(mParent.getTheme());
                } catch (Exception e) {
                    // Empty
                }
                theme.applyStyle(resid, false);
            }
    
            // Get the primary color and update the TaskDescription for this activity
            if (theme != null) {
                TypedArray a = theme.obtainStyledAttributes(com.android.internal.R.styleable.Theme);
                int colorPrimary = a.getColor(com.android.internal.R.styleable.Theme_colorPrimary, 0);
                a.recycle();
                if (colorPrimary != 0) {
                    ActivityManager.TaskDescription v = new ActivityManager.TaskDescription(null, null,
                            colorPrimary);
                    setTaskDescription(v);
                }
            }
        }
    

    下一篇:介绍下Android系统有哪些常见的主题

    相关文章

      网友评论

        本文标题:Android样式和主题(一):简介

        本文链接:https://www.haomeiwen.com/subject/mioltxtx.html