ImageView的高级使用技巧

来源:互联网 发布:淘宝商品列表代码 编辑:程序博客网 时间:2024/06/05 21:07

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

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





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


使用background加src来实现

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


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

<?xml version="1.0" encoding="utf-8"?><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中的代码:

<?xml version="1.0" encoding="utf-8"?><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-listxmlns: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上面。来看下过度绘制的问题:


我们看到过度绘制的问题已经不存在了。


总结

说了这么多小的使用技巧,对我们平时的开发是非常有帮助的。有的技巧会使代码变得整洁,有的会取消掉过度绘制的问题。但是由于google设计的缺陷,过度绘制和代码的整洁行没有办法同时做到,我们以后在开发中需要灵活的运用。如果你对这块有更好的理解,欢迎在下面指出来,谢谢~~~





欢迎关注我的微信公众号“android教科书”,最新最好的文章第一时间送到手!可以扫描下面的二维码来关注:




0 0
原创粉丝点击