转载注明出处:http://blog.csdn.net/xiaohanluo/article/details/52945791
1. 概述
Android研发中经常会遇见圆角或者圆形图片的展示,但是系统中ImageView并不能直接支持,需要我们自己做一些处理,来实现圆角图片或者圆形图片,自己最近对这块的实现做了一下总结,看以下几种实现方法。
- 图层叠加,上层覆盖一层蒙版,遮挡图片,让图片展示出圆角或者圆形效果
- 重新绘制
- BitmapShader
- Xfermode
- RoundedBitmapDrawable
- CardView,使用官方控件,自动裁剪,达到圆角或者圆形效果。(5.0以上系统)
第一种方法,很傻,不太优雅,不推荐这种方法,了解这种方法是因为确实看见有人这么做过。推荐使用第二种方法,重新绘制图片,不仅可以绘制出四角圆角图片,还可以绘制出底部/顶部/左边/右边圆角效果,非常方便。如果想要偷懒,可以直接使用RoundedBitmapDrawable来实现圆角照片效果。而第三种方法,使用CardView
控件有很大的局限性,它只在5.0以及以上的系统中有效。
下面就来看一下各种方法的具体情况吧。
2. 图层叠加
图层叠加原理很简单,就是在一张图片上面叠加一层图,覆盖部分,让图片展示成圆角。具体原理可以参考下面这张图。
图-1 图层叠加原理图
看一下布局代码,很简单。
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin">
<FrameLayout
android:layout_width="100dp"
android:layout_height="100dp"
android:background="@drawable/demo_icon_android_logo">
<ImageView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:src="@drawable/demo_icon_shader"/>
</FrameLayout>
</RelativeLayout>
运行结果如下:
图-2 图片叠层运行结果图
效果还是可以的,但是缺点也很明显,一是要准备两张图片,会增加额外的包体积;二是图片叠加一起,必然导致过度绘制;三是该方法太死板,使用时候要考虑图片大小,控件大小,以及蒙层图圆角锯齿效果,非常不灵活,Java里面不灵活就意味着可用性不强。
所以这种方法不建议使用,大家作为了解就行。提出这种方法是为了让大家了解一下图层,后面重新绘制过程中,有一种方法逻辑跟这个相似,也是绘制图层叠加,生成圆角图片。
3. 重新绘制
对图片的绘制要特别的注意,有时候可能图片太大需要我们压缩,关于图片压缩大家可以查看这片文章压缩图片。重新绘制图片,将图片绘制成圆角,有三种方法。
- 使用BitmapShader
- 使用Xfermode
- 使用RoundedBitmapDrawable
从性能上讲并没有太大的区别,但是从使用灵活性上说,个人推荐使用BitmapShader。
在介绍这三个方法之前,先介绍一下图片的拉伸缩放适配,大多数情况先,要展示图片的控件(ImageView)的长宽和图片的长宽并不是一致的,甚至长宽比都不一致,所以在拿到一张图片时候,大多数情况下需要根据控件的大小对图片进行拉伸缩放处理,有人会问为什么不直接使用ImageView
属性scaleType
去控制拉伸缩放,这是因为当我们将一个Bitmap绘制成圆角后,再去进行拉伸缩放,圆角可能会变形,所以在Bitmap设置到控件之前就需要对Bitmap进行一下拉伸缩放处理,直接看下面代码。
// 图片根据控件大小等比例缩放拉伸
float widthScale = imageViewWidth * 1.0f / bitmap.getWidth();
float heightScale = imageViewHeight * 1.0f / bitmap.getHeight();
// 设置长宽拉伸缩放比
Matrix matrix = new Matrix();
matrix.setScale(widthScale, heightScale);
// 拉伸缩放图片
Bitmap newBt = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);
注:拉伸缩放也可以在Canvas.drawBitmap(Bitmap bitmap, Rect src, Rect dst, Paint paint)方法中控制,后面会提及到。
3.1 BitmapShader绘制圆角
所有的绘制圆角的实现,推荐使用这个方法,不仅仅可以帮助我们实现圆角,连部分圆角都可以实现,比如顶部是两个圆角,底部是两个直角的图片。
首先介绍一下BitmapShader
这个类,它作为纹理用于绘制一张图。新图可以是纹理图重复/镜像/边缘像素拉伸而绘制成的新图。这个类构造函数很简单,BitmapShader(Bitmap bitmap, TileMode tileX, TileMode tileY)
,第一个参数是Bitmap,作为纹理图传入,tileX是指在水平方向上的绘制方式,tileY是指在竖直方向上的绘制方式。TileMode
有三种属性,拉伸、重复、镜像。
- TileMode.CLAMP 拉伸绘制,并不是指图片拉伸,而是指图片最后一个像素不断绘制,纹理图水平或者竖直方向最后一个