安卓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传过去。

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值