美文网首页Android开发Android开发经验谈Android技术知识
Android 动态实现圆角背景和图标换色小技巧

Android 动态实现圆角背景和图标换色小技巧

作者: Android小Y | 来源:发表于2019-02-28 18:03 被阅读13次

    前言

    不知道你们有没有遇到这样一种场景:

    设计师:“首页这个按钮圆角度数为5个像素”

    你:“OK”,言语间你已经在drawable目录下创建了一个xml文件,定义了圆角的shape,然后给Imageview设置上:

    <?xml version="1.0" encoding="utf-8"?>
        <shape xmlns:android="http://schemas.android.com/apk/res/android">
        <solid android:color="#f1de11"/>
        <corners android:radius="5px"/>
    </shape>
    

    过了5分钟……

    设计师:顶部的Tab选中时的背景也给它红色圆角8像素吧

    你:“可以”。反正举手之劳,再建个xml就好了”

    过了一会儿ui复审…

    设计师:“新消息提醒改成小圆形吧”

    你内心:Orz…再这么建下去…

     
    开个玩笑,不过确实很多时候我们的项目中会存在很多圆角背景的ui,而且一般都还每个地方的圆角度数都略有差别,这种时候是不是内心有一种特别想动态更改xml的属性的冲动(不然每个都对应一个文件到时候岂不是一堆),既然xml不可以,何不试一下代码上动态生成呢?

     


    动态实现圆角背景

    我们都知道ImageView可以设置Drawable,如果我们动态生成一个圆角的Drawable岂不美哉,恰好Android中有这么一个类GradientDrawable,它继承于Drawable,提供了各种shape标签的属性设置接口,转换成对应形态的Drawable对象。因此我们可以定义这么一个方法,只需传入圆角度数、颜色和边缘宽度,以及是否填充,即可得到一个等同于xml效果的Drawable资源对象:

    public static GradientDrawable getRoundRectDrawable(int radius, int color, boolean isFill, int strokeWidth){
            //左上、右上、右下、左下的圆角半径
            float[] radius = {radius, radius, radius, radius, radius, radius, radius, radius};
            GradientDrawable drawable = new GradientDrawable();
            drawable.setCornerRadii(radius);
            drawable.setColor(isFill ? color : Color.TRANSPARENT);
            drawable.setStroke(isFill ? 0 : strokeWidth, color);
            return drawable;
    }
    

     
    使用:

     ImageView imageView = findViewById(R.id.image_view);
     imageView.setBackground(ShapeUtils.getRoundRectDrawable(40, Color.parseColor("#5bc0de"), true, 10));
    

     
    效果如图:


    动态生成圆角图

    就再也不用因为某个小属性的差别而新建那么多的xml文件,减少了apk的体积,但是另一方面,毕竟是动态生成的Drawable,所以性能上会略有影响,因此要根据实际需要可采用动态方式和静态方式相结合。(此处只是举例最简单的shape例子,其它属性设置可参见API或文末Github地址)

     

    动态图标换色

    另外一种场景,就是很多app都会有底部tab用于切换主功能,当前选中的那个tab的图标肯定和其他未被选中的tab的图标不一样,有些是做了一些动画效果并且对图标细节进行了一定调整,另外一些是图标无论是否被选中,都是那样的形状,只是单纯换了个颜色,这种情况我们一般会让ui再另外切一套着色了的图标,然后代码中动态切换图标,达到切换tab的效果。但这种方式同样存在一个问题,两套一摸一样的图标,只是颜色不一样,这样会不会有点占用apk体积,是否可以通过动态给Icon涂上颜色呢?

    答案是可以的,同样是通过Drawable来操作,图标本身可以通过getDrawable转换为Drawable对象,然后再通过DrawCompat来进行重新着色:

     /**
         * 将drawable颜色着色为color
         * @param drawable
         * @param color
         * @return 重绘后的Drawable
         */
        public static Drawable drawColor(Drawable drawable, int color) {
            final Drawable wrappedDrawable = DrawableCompat.wrap(drawable);
            wrappedDrawable.mutate();
            DrawableCompat.setTint(wrappedDrawable, color);
            return wrappedDrawable;
        }
    

     
    首先DrawableCompat.wrap是将drawable转换为可着色的Drawable对象,然后调用mutate是表示只对当前这个对象进行着色,假如不调用这句,到时候一着完色,以后再getDrawable获取这个对象的时候,就都变成着色后的了(即拿不到之前原来的那个Drawable了),然后setTint就是将我们想要重绘的颜色绘制上去了,最后将新的Drawable返回,同样设置给ImageView,就可以变成另外一个颜色的Icon了。

    弄了个简单的动画,不断对icon进行染色:

    final ImageView imageView = findViewById(R.id.image_view);
    ValueAnimator animator = ValueAnimator.ofArgb(Color.parseColor("#3F51B5"),Color.parseColor("#FF4081"));
            animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
                @Override
                public void onAnimationUpdate(ValueAnimator animation) {
                    int color = (int)animation.getAnimatedValue();
                    imageView.setBackground(ShapeUtils.drawColor(getResources().getDrawable(R.drawable.ic_android), color));
                }
    });
    

     
    效果如图:


    图标染色

     

    总结

    这两种方式有时候在特别多重复但却有略微差别的ui场景中可以派上用场,另外还可以用来统一控制某些图标的颜色或者多个圆角的控制,都是以时间换空间的方式,结合实际情况进行运用。
    这里只是列举了几个shape的常用属性,它还有其他很多属性可以动态设置,把它们封装成了一个工具类,代码已传到 GitHub-ZJYWidget 。里面有很多实用的自定义View源码及demo,会长期维护,欢迎Star~ 如有不足之处或建议还望指正,相互进步,如果觉得不错动动小手给个喜欢, 谢谢~

    相关文章

      网友评论

        本文标题:Android 动态实现圆角背景和图标换色小技巧

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