Android-Tint使用实践

Tint 是什么?

  Tint,翻译过来意思就是染色。自Android-L(5.0)之后,出现了新的设计语言:Material design,瞬间丰富了app的设计主题与动画,同时也对开发者对于用户交互提出了指导。那主题之间的切换是如何做到的呢?使用Theme.AppCompat,随着Theme中的colorPrimary,colorPrimaryDark,colorAccent颜色的变化,相应主题就发生改变,其实这一切都是Tint完成的。其实严格来说,在5.0之前该功能我们就能实现,只是google在5.0后对它关键字化,将它从PorterDuffColorFilter独立出来,在xml和代码中均可以使用tint的一系列指令和api实现相关功能。在后面我们会就这一问题进行讨论。

  好处?节约资源啊,同1张图片的资源,如果用的合适,可以使用在多个地方。


Tint 小实践.

  项目中现在有这样一个需求。

     消耗占比星级显示规则

     

消耗占比

星级

颜色

7.5%

一星

红色

[ 7.5%10%

二星

橙色

≥10%

三星

绿色

    

       实际就是根据消耗占比,显示不同的星星个数以及颜色。包括背景色星星在内,设计给我们切了4张图。实际上如果使用tint功能,我们是不用添加这几张图片的。

      假设你的项目对版本的支持比较高(>=21),那么下列几行代码就基本可以实现相关功能。             

<RatingBar
        android:id="@+id/rating_1"
        android:layout_width="wrap_content"
        android:progressTint="@color/data_text_star1"
        android:layout_height="wrap_content" />

      代码中,我们获取到RatingBar,然后在代码重新设置颜色即可。

super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        RatingBar myRatingBar1 = (RatingBar) findViewById(R.id.rating_1);        

      但是大部分时候,我们是不会支持这么高版本,我们需要兼容以前的版本,这个时候如何做到呢。不得不说,这样的功能对于客户端开发者来说,的确是不错福音,有时候能够节省一定量的图片资源,在ios7中也加入了tintColor这一属性。那它是如何实现的呢。关键代码其实也就几行:

      if(filter == null){  

// Caches misses create a color filter and add it to the cache  

filter = new ProterDuffColorFilter(color, mode);  

}  

d.setColorFilter(filter);


        没错,就是通过ProterDuffColorFilter实现的.这类东东我们在使用自定义圆角图片的时候,经常跟它打交道,这一次google直接在sdk中帮我们实现了这个功能,获取到图片的drawable,然后设置drawable的colorFilter,默认的mode是src_in的,典型的新瓶装旧酒。

        如果使用以前的api,我们应该如何实现呢:

LayerDrawable drawable = (LayerDrawable) getProgressDrawable();
            Drawable drawable0 = drawable.getDrawable(2);
            tintDrawable(drawable0,ColorStateList.valueOf(getResources().getColor(R.color.data_text_star2)));
            Drawable drawable1 = drawable.getDrawable(1);
            drawable0.setColorFilter(getResources().getColor(R.color.data_text_star2), PorterDuff.Mode.SRC_IN);
            drawable1.setColorFilter(getResources().getColor(R.color.data_text_star2), PorterDuff.Mode.SRC_IN);
        

        会稍微麻烦一些,我们看看不妨看看系统代码也是如何实现的:

       @RemotableViewMethod

    public void setProgressTintList(@Nullable ColorStateList tint) {
        if (mProgressTintInfo == null) {
            mProgressTintInfo = new ProgressTintInfo();
        }
        mProgressTintInfo.mProgressTintList = tint;
        mProgressTintInfo.mHasProgressTint = true;

        if (mProgressDrawable != null) {
            applyPrimaryProgressTint();
        }
    }
       继续看,核心方法是applyPrimaryProgressTint():      

private void applyPrimaryProgressTint() {
        if (mProgressTintInfo.mHasProgressTint
                || mProgressTintInfo.mHasProgressTintMode) {
            final Drawable target = getTintTarget(R.id.progress, true);
            if (target != null) {
                if (mProgressTintInfo.mHasProgressTint) {
                    target.setTintList(mProgressTintInfo.mProgressTintList);
                }
                if (mProgressTintInfo.mHasProgressTintMode) {
                    target.setTintMode(mProgressTintInfo.mProgressTintMode);
                }

                // The drawable (or one of its children) may not have been
                // stateful before applying the tint, so let's try again.
                if (target.isStateful()) {
                    target.setState(getDrawableState());
                }
            }
        }
    }
      这次换成了drawable的setTinitList():  

@Override
    public void setTintList(ColorStateList tint) {
        final BitmapState state = mBitmapState;
        if (state.mTint != tint) {
            state.mTint = tint;
            mTintFilter = updateTintFilter(mTintFilter, tint, mBitmapState.mTintMode);
            invalidateSelf();
        }
    }
    updateTintFilter():

@Nullable PorterDuffColorFilter updateTintFilter(@Nullable PorterDuffColorFilter tintFilter,
            @Nullable ColorStateList tint, @Nullable PorterDuff.Mode tintMode) {
        if (tint == null || tintMode == null) {
            return null;
        }

        final int color = tint.getColorForState(getState(), Color.TRANSPARENT);
        if (tintFilter == null) {
            return new PorterDuffColorFilter(color, tintMode);
        }

        tintFilter.setColor(color);
        tintFilter.setMode(tintMode);
        return tintFilter;
    }

     找到了,的的确确系统调来调去,最后就是通过PorterDuffColorFilter来实现的。


     上面只是单单举例ratingbar中的使用,实际上Tint适用于所有包含图片的控制。这样一个例子:



         

下载地址: demo下载


       

         


  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值