圆形ImageView系列(二)-----Xfermode+ImageView
2016-02-15 11:46
417 查看
前言
上一篇文章《 圆形ImageView系列(一)—–Xfermode+View》介绍了Xfermode,并且结合View实现了圆形ImageView,这种方式实现的思路和方法都很简单,但是使用起来总感觉少了点什么。既然是圆形ImageView,但是原生的ImageView的很多属性却使用不了,比如scaleType等等,所以下面我们使用第二种方案。
主要原理
在ImageView的上面覆盖一个遮罩层,将这个遮罩层的中间抠掉一个圆形之后,整个ImageView看起来就能显示出圆形的效果了。先来看看效果图。
上面那张效果图里,下面的两张图可以明显的看到有个白色的遮罩层覆盖在ImageView上面,所以看起来就显示成了圆形ImageView的效果。
具体实现
[code]package com.passerby.androidadvanced.circleimage.imageview; import android.content.Context; import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.graphics.PorterDuff; import android.graphics.PorterDuffXfermode; import android.graphics.drawable.ColorDrawable; import android.graphics.drawable.Drawable; import android.util.AttributeSet; import android.widget.ImageView; /** * Created by mac on 16/2/3. */ public class CircleLayerImageView extends ImageView { public CircleLayerImageView(Context context) { this(context, null); } public CircleLayerImageView(Context context, AttributeSet attrs) { this(context, attrs, 0); } public CircleLayerImageView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); int width = getMeasuredWidth(); int height = getMeasuredHeight(); //创建跟imageview相同宽高的遮罩层 int min = Math.min(width, height); Bitmap bitmapMask = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888); Canvas canvasMask = new Canvas(bitmapMask); //遮罩层颜色 int maskColor; Drawable background = getBackground(); if (background != null && background instanceof ColorDrawable) { maskColor = ((ColorDrawable) background).getColor(); } else { maskColor = Color.WHITE; } canvasMask.drawColor(maskColor); Paint paint = new Paint(); paint.setAntiAlias(true); paint.setColor(Color.WHITE); canvas.saveLayer(0, 0, width, height, paint, Canvas.ALL_S***E_FLAG); canvas.drawBitmap(bitmapMask, 0, 0, paint); paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_OUT)); canvas.drawCircle(width >> 1, height >> 1, min >> 1, paint); canvas.restore(); } }
看到这么少的代码是不是吓尿了,之所以这么少是因为是直接继承的ImageView,很多工作ImageView已经帮我们完成了。
代码第34行,要记得调用父类的onDraw方法,不然imageView原本的图片没法正常显示。
第39~42行,创建了一个跟imageView相同大小的遮罩层Bitmap,新建了一个canvas并且将bitmap作为参数传进去。注意这里是新建的一个canvas,而不是直接使用onDraw里面系统传入的canvas,因为我们只需要对这个遮罩bitmap画上颜色而已,如果直接使用系统的canvas,那遮罩层的颜色就画在imageView上面而不是遮罩bitmap上面了。
第44~54行,主要设置遮罩层的颜色,这个颜色从ImageView的background属性中获取,这样就不会使遮罩层显得十分突兀,比如你可以看看上面效果图里面我做了一个actionBar的效果,将圆形ImageView的background跟外面的布局颜色设置成一样,看上去效果就非常好了。
当然为了容错,有人可能不小心将background设置成了图片或者其他drawable,这里默认就设置成白色的遮罩层颜色。
第60~68行,一共5行代码,主要用到了canvas的layer知识。了解photoshop的同学对图层的概念应该非常熟悉,包括我们常用的地图软件也有很多不同的图层,具体知识请百度,这里只需要注意canvas.saveLayer和canvas.restore要成对使用就好。
第62行,将遮罩层画在新的图层上,遮罩层将作为src。
第64行,改变画笔的xfermode模式,对照之前的表,应该选取srcOut模式。
第66行,将适当大小的圆画在遮罩层上面,结合画笔的xfermode模式,画完之后的效果相当于遮罩层被抠掉了一个圆形,位于遮罩层之下的imageview就显示成圆形的效果了。
相关文章推荐
- js调试工具Console命令详解
- Light OJ 1257 Farthest Nodes in a Tree (II) (树形DP)
- NodeJS获取命令行后面的参数
- cdnjquery加载失败加载本地
- java之HeapByteBuffer&DirectByteBuffer以及回收DirectByteBuffer
- 【JSTL】--测试EL表达式--drp212~
- css中的:before与:after的简单使用
- javascript异步执行的一些例子
- node
- JavaScript中的注意事项
- 传奇创世h5开发案例分享:京东物流春节不打烊 寻宝赢限量joy SAGA与你相约
- JavaScript中的的垃圾回收机制
- web前端基础——初识HTML DOM编程
- HTML 属性总结
- jQuery命名空间无冲突
- HTML5离线Web应用实战:五步创建成功
- JavaScript中的执行环境
- js中数组(Array)重排序方法深析
- HTML5与php实现消息推送功能
- 使用css3 实现旋转的立方体