万明智的博客

个人学习交流博客,关于安卓,java的一些东西。23种设计模式,编程思想。项目中实用的一些代码,一些bug原因及修复...

安卓theme与style详解

   安卓app作为一个有界面的程序,谷歌给我们提供了很多UI控件。而控件是功能性的,具体的控件样式却是需要我们自己去控制的。这也就引出了今天话题,安卓的theme与style。说到这个,大家可能都知道theme是主题,也就是整个app的样式。而style是样式,控制的是单个View。是的,希望我们在应用的时候也要铭记这点。

也就是说theme是针对application和activity的,当然也不是所有都是这样的,比如toolbar就可以设置theme。一开始toolbar是特例,但后来谷歌推出了ThemeOverlay使得一般view也可以使用theme。而且会传递给子控件。theme原理是什么呢,我们来看看View的构造方法。

public View(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
    this(context);

    final TypedArray a = context.obtainStyledAttributes(
            attrs, com.android.internal.R.styleable.View, defStyleAttr, defStyleRes);
可以看到是使用的context对象得到的属性数组,这也是所有的View构造方法要包含context的原因。具体参数意义及作用顺序,你也可以直接看里面结论就好了。

其实控制theme不难,难的是控制一个view的style,因为它跟theme还有关系。比如现在我改变了一个activity的theme,我如何让里面的View用原theme的样式呢?为了回答这个问题,我们先来看Dialog源码。因为Dialog是可以设置Theme的,而且不影响原来的activity。

Dialog(@NonNull Context context, @StyleRes int themeResId, boolean createContextThemeWrapper) {
    if (createContextThemeWrapper) {   
        if (themeResId == 0) {
            final TypedValue outValue = new TypedValue();
            context.getTheme().resolveAttribute(R.attr.dialogTheme, outValue, true);
            themeResId = outValue.resourceId;
        }
        mContext = new ContextThemeWrapper(context, themeResId); //可以看到true时,会创建一个这种对象

    } else {
        mContext = context;
    }
那么,不是有一个context,为什么要重新生成一个ContextThemeWrapper呢。关于context点这里,我们来看看这个ContextThemeWrapper

/**
 * A ContextWrapper that allows you to modify the theme from what is in the 
 * wrapped context. 
 */
public class ContextThemeWrapper extends ContextWrapper {
    private int mThemeResource;
    private Resources.Theme mTheme;
    private LayoutInflater mInflater;
    private Configuration mOverrideConfiguration;
    private Resources mResources;

    public ContextThemeWrapper() {
        super(null);
    }

    public ContextThemeWrapper(Context base, @StyleRes int themeResId) {
        super(base);
        mThemeResource = themeResId;
    }

    public ContextThemeWrapper(Context base, Resources.Theme theme) {
        super(base);
        mTheme = theme;
    }..............
可以看到重写了theme相关的方法和属性,而且从类的介绍也可以看出。回到原来的问题,我们可以通过new一个这个类的对象给View传过去。

阅读更多
版权声明:本文为博主原创文章,转载请注明出处。 https://blog.csdn.net/wanyouzhi/article/details/53668411
文章标签: theme style android
个人分类: android
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页

加入CSDN,享受更精准的内容推荐,与500万程序员共同成长!
关闭
关闭