最近因为需求需要用到圆形图片,因为不能去引用一些三方库,并且也不是什么特别难的自定义View,因此自己动手y用 BitmapShader
实现了一个,在 Android 上实现自定义形状图片还有其他几种方式,特此记录一下~
ClipPath
这种方式应该是实现自定义形状图片最简单的方式了,只需要继承 ImageView
,并在 onDraw
方法中,在执行 super.onDraw()
之前,调用clip方法对画布进行裁剪即可,需要注意的是,在 API 18 以下,需要关闭硬件加速。
1 | override fun onDraw(canvas: Canvas) { |
这种方式实现虽然简单,但缺点就是裁剪出的图片仔细看的话,会发现有锯齿,而且也无法添加阴影或其他扩展,因为画布的大小已经是圆形区域这么大了。
BitmapShader
关于 BitmapShader ,可以看看爱哥的自定义View博客的第四篇 自定义控件其实很简单1/3。
Github 上一个著名的圆形图片库 CircleImageView 就是使用这种方式来实现的。
1 | private fun drawableToBitmap(drawable: Drawable) : Bitmap { |
PorterDuffXfermode
关于混合模式的相关概念可参考 自定义控件其实很简单1/6
这里只需要关注 SRC_IN
和 DST_IN
两种模式即可,其实主要就是理解这张图:
因此实现方式也是很简单,这里比如说使用 SRC_IN
模式:
1 | fun initPaint() { |
这里需要注意的是,要在绘制 bitmap 完成后,即使将 Paint.xfermode 设置为 null 来清除混合模式。
阴影
有些时候我们可能需要给 View 加个背景阴影来使 View 显得立体一点,此时就需要用到 Paint 的 setShadowLayer()
这个方法了,其中,radius 是阴影半径,越大阴影越发散,为0时不显示,dx 和 dy 分别为 X 轴和 Y 轴的偏移量,shadowColor 就不用说了,阴影的颜色嘛~1
public void setShadowLayer(float radius, float dx, float dy, int shadowColor)
比较
总体而言,使用 ClipPath
来实现最为简单,只需要继承 ImageView
即可,但缺点就是前面说的锯齿问题,其他两种方式,虽然是继承 ImageView
来实现,但具体绘制还是要自己来实现,而且还得自己去支持 ScaleType
,如果是需要用到占位图,那还得根据占位图是否需要进行裁剪来做相应的操作,还有就是需要对 drawable 做适配,因为占位图有可能不是 bitmap,如 vector等。