ImageView的高级使用技巧

http://mp.weixin.qq.com/s/Rg213sQQ2ge4ARRzzxH4pw

看到一篇很使用的文章,想记录下来,已标注转载,莫怪!

mageView是大家用的非常多的控件之一,其相比于其他控件多了一个src属性。我们平时在其中显示的图片往 往需要跟随外部的变化切换图片,这个时候我们一般会选择用多张图片来实现,如果变化后的图片和原图很类似,只是更改了颜色我们完全没有必要去弄张新图片 来,今天就来教大家如何实现这种情况的需求。


如何使用Imageview的问题我就不再多说了,现在我们要实现下面这样一个Imageview:



一个圆形的Imageview,但是圆形的图片颜色和中间的那个src图片和其颜色都是可以变化的,比如这个是一个安全类的app,在扫描到有病毒的时候会 根据病毒的类型变化成不同的样式。现在我们假定有3中状态:无病毒、低风险病毒、高风险病毒,分别对于上面的三个状态。对于这样一个情况,你可能会使用多 张图片来实现,这样带来的后果就是增加项目的工作量和app的大小。我们如何使用最少的图片来实现呢?



使用background加src来实现

你可能最先想到的是分两个部分,第一个是圆形的纯色部分使用背景来实现,中间使用图片来实现。我们照着这个思路来实现第一种效果,打开手机开发者选项里面的过度绘制,来看看层级:


过度绘制的颜色从低到高分别是:蓝色-绿色-淡红-红色,分别对应x1-x2-x3-x4的绘制次数。很明显我们这里存在两层的绘制问题。这么我们的布局文件是这样的:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/activity_main"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <ImageView
        android:id="@+id/imgv_toHint"
        android:layout_width="200dp"
        android:layout_height="200dp"
        android:layout_centerInParent="true"
        android:background="@drawable/imgv_bg"
        android:padding="30dp"
        android:scaleType="centerInside"
        android:src="@drawable/center_icon" />
</RelativeLayout>


这里的Imageview分别设置了一个背景和一个图片,那么我们如何根据状态来设置对应的状态呢?来看java代码部分:

  imgv_toHint = (ImageView) findViewById(R.id.imgv_toHint);
        LightingColorFilter bFilter = new LightingColorFilter(Color.TRANSPARENT, getResources().getColor(R.color.imgv_bg_yellow));
        imgv_toHint.getBackground().setColorFilter(bFilter);
        LightingColorFilter iFilter = new LightingColorFilter(Color.TRANSPARENT, getResources().getColor(R.color.src_bg_second));
        imgv_toHint.getDrawable().setColorFilter(iFilter);


运行效果:



运行之后就可以看到和第二种效果是一样的,这种方式有点略屌。使用了一个ColorFilter来对图像进行处理,其中ColorFilter是一个抽象的类,不能直接来使用,需要使用其子类,他的子类有3个:  LightingColorFilter、 ColorMatrixColorFilter、PorterDuffColorFilter;具体的使用我这里就不过多的展开了,有兴趣的同学可以深入的学习下,对处理图片是非常有用的。当然还可以使用图片中的各种tint属性来实现,这里就不再具体的演示如何实现了。




使用layer-list加level-list来实现

layer-list:其实质是给其中定义的item中的图片按照顺序一张张的绘制上去,默认是绘制一样的大小,但是我们可以指定偏移量来达到不一样的大小。

level-list:其实质是定义多张图片对应多个状态(使用int值来表示),在代码中我们设置不同的状态来控制显示不同的图片。


我们来看xml中的代码:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/activity_main"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <ImageView
        android:id="@+id/imgv_toHint"
        android:layout_width="200dp"
        android:layout_height="200dp"
        android:layout_centerInParent="true"
        android:src="@drawable/level_icon" />
</RelativeLayout>


来看看level_icon文件:

<?xmlversion="1.0" encoding="utf-8"?>
<level-list
xmlns:android="http://schemas.android.com/apk/res/android">
    <item
        android:drawable="@drawable/layer_bg_first"
        android:maxLevel="1"/>
    <item
        android:drawable="@drawable/layer_bg_secend"
        android:maxLevel="2"/>
    <item
        android:drawable="@drawable/layer_bg_third"
        android:maxLevel="3"/>
</level-list>


来看看其中一个layer-list:

<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
    <item
        android:width="160dp"
        android:height="160dp"
        android:drawable="@drawable/imgv_bg_first" />
    <item
        android:width="100dp"
        android:height="100dp"
        android:drawable="@drawable/center_icon_first"
        android:left="30dp"
        android:top="30dp" />
</layer-list>


在代码中我们可以这样使用:

  imgv_toHint = (ImageView) findViewById(R.id.imgv_toHint);
        imgv_toHint.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                imgv_toHint.getDrawable().setLevel(level = level >= 3 ? 1 : ++level);
            }
        });


获取到drawable对象,然后设置其level系统就自动更换图片了


这 种方式可以做到最少的代码来控制图片的更换,用一个变量来控制图片自动显示,使代码非常的整洁,但是其也有一个不好的地方就是可能会增加图片的数量。具体 的取舍需要根据具体的项目来考虑。当然我们也可以结合tint属性和colorfilter来减少图片的数量,但是又增加了代码的数量。这种方式也存在过 度绘制的问题。

说了这么多,过度绘制的问题还是没能解决,其根本原因是我们还没有给他们做到一张图片来显示。如果要做到一张图片显示又不 过多的引入图片的数量,我们可以使用一个bitmap对象来绘制一张图片然后设置到imageview上面去。因为bitmap在绘制的时候不管是多么复 杂,其也算是一层view。利用这个思路,我们来减少过度绘制的问题。




去掉过度绘制的问题

这种方式就不能够在xml文件中直接设置src图片了,因为前面我们知道这种方式设置的话是行不通的。那么我们只能在代码中来设置,我们可以给资源文件中的layer-list转化为一张图片,然后设置到imageview上面,这样的话多了一层转化少了一层绘制。

来看java中的代码:

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        imgv_toHint = (ImageView) findViewById(R.id.imgv_toHint);
        Drawable src = getDrawable(R.drawable.layer_bg_secend);
        imgv_toHint.setImageBitmap(drawable2Bmp(src));
    }
    private Bitmap drawable2Bmp(Drawable drawable) {
        Bitmap bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight(),
                drawable.getOpacity() != PixelFormat.OPAQUE ? Bitmap.Config.ARGB_8888 : Bitmap.Config.RGB_565);
        Canvas canvas = new Canvas(bitmap);
        drawable.setBounds(0, 0, drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight());
        drawable.draw(canvas);
        return bitmap;
    }


这里我们定义了一个drawable转为Bitmap的方法,给资源中的drawable对象转化为一张bitmap图片,然后设置到imageview上面。


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值