100字范文,内容丰富有趣,生活中的好帮手!
100字范文 > android 图片圆角 遮罩_Android 自定义View练手Demo(一)实现圆角遮罩效果

android 图片圆角 遮罩_Android 自定义View练手Demo(一)实现圆角遮罩效果

时间:2020-07-24 02:30:39

相关推荐

android 图片圆角 遮罩_Android 自定义View练手Demo(一)实现圆角遮罩效果

Android 自定义View系列文章

Android自定义View实现圆角遮罩效果

一图胜千言,有一个遮罩就会凸显出重点区域

1-1.jpg

本文通过两种方式来实现这种效果,来达到自定义View练手的效果

此效果的用途

在裁剪图片,确定裁剪范围

在APP中引导用户,突显某个区域

这是一个麻雀虽小五脏俱全的小Demo了,非常适合练手。

1.引言

通过本文可以学习到

Canvas和Paint 的常用且实用的 API

Xfermode的使用

View级别的离屏缓冲的开启方式

Canvas的离屏缓冲和View的离屏缓冲的区别

如何给自定义View设置自定义属性的使用

2.第一种实现方式

class RoundRectCoverView(context: Context, attrs: AttributeSet) : View(context, attrs) {

private val paint = Paint(Paint.ANTI_ALIAS_FLAG)

private var mPadding = 40.dp //间距

private var mRoundCorner = 10.dp //圆角矩形的角度

private var mCoverColor = "#99000000".toColorInt()//遮罩的颜色

private val porterDuffXfermode = PorterDuffXfermode(PorterDuff.Mode.SRC_OUT)

init {

//开启View级别的离屏缓冲,并关闭硬件加速,使用软件绘制

setLayerType(LAYER_TYPE_SOFTWARE, null)

}

override fun onDraw(canvas: Canvas) {

//先画一个圆角矩形,也就是透明区域(Destination image)

canvas.drawRoundRect(mPadding, mPadding, width - mPadding, height - mPadding, mRoundCorner, mRoundCorner, paint)

//设置遮罩的颜色

paint.color = mCoverColor

//设置paint的 xfermode 为PorterDuff.Mode.SRC_OUT

paint.xfermode = porterDuffXfermode

//画遮罩的矩形(Source image)

canvas.drawRect(0f, 0f, width.toFloat(), height.toFloat(), paint)

//清空paint 的 xfermode

paint.xfermode = null

}

上面代码中的注释已经写的很清楚了,这里说一下 setLayerType(LAYER_TYPE_SOFTWARE, null) 是开启View级别的离屏缓冲,就是拿出整个View大小的一块区域,这块区域是透明的。那么你就可能会好奇,为啥要拿出这么一块透明的区域呢?因为使用PorterDuff.Mode时候需要用到。

这里面我们用到的是PorterDuff.Mode.SRC_OUT,正好对应的是Source Out这种模式是我们想要的

注意Destination image是第一次画的圆角矩形,需要画在一个透明的View中,这就需要离屏缓冲

Source image是画的带颜色的遮罩也就是整个View

PorterDuff.Mode.SRC_OUT,类似于把后画的和先前画的重叠的部分,抠出去扔掉,结果就是我们要的效果

3.第二种实现方式

class RoundRectCoverView(context: Context, attrs: AttributeSet) : View(context, attrs) {

private val paint = Paint(Paint.ANTI_ALIAS_FLAG)

private var mPadding = 40.dp //间距

private var mRoundCorner = 10.dp //圆角矩形的角度

private var mCoverColor = "#99000000".toColorInt()//遮罩的颜色

private val bounds = RectF()

private val porterDuffXfermode = PorterDuffXfermode(PorterDuff.Mode.SRC_OUT)

private val clipPath = Path()

override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) {

//设置离屏缓冲的范围

bounds.set(0f, 0f, width.toFloat(), height.toFloat())

//设置Clip Path的矩形区域

clipPath.addRoundRect(mPadding, mPadding, width - mPadding, height - mPadding, mRoundCorner, mRoundCorner, Path.Direction.CW)

}

override fun onDraw(canvas: Canvas) {

//Canvas的离屏缓冲

val count = canvas.saveLayer(bounds, paint)

//KTX的扩展函数相当于对Canvas的 save 和 restore 操作

canvas.withSave {

//画遮罩的颜色

canvas.drawColor(mCoverColor)

//按Path来裁切

canvas.clipPath(clipPath)

//画镂空的范围

canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.SRC)

}

//把离屏缓冲的内容,绘制到View上去

canvas.restoreToCount(count)

}

}

解释一下,在onSizeChanged方法中,我们设置了离屏缓冲的范围,注意这个范围够用就行,太大了耗费性能。同时设置了Clip Path裁剪的矩形区域。

onDraw方法中

首先开启离屏缓冲(注意这里开启的是Canvas的离屏缓冲)这范围就是bounds的范围

画出完整的遮罩的颜色

然后把Canvas裁切出一个圆角矩形

然后在话一个透明的颜色,模式指定为PorterDuff.Mode.SRC

把离屏缓冲的内容,绘制到View上去

注意:记得开离屏缓冲,否则结果可能不是你想要的

4.设置自定义属性

4.1首先在values文件夹下,创建一个attrs.xml的文件(当然你也可以叫别的名字,但这个是规范)

声明你想再xml中能设置的属性,比如我这里声明了,圆角的大小,圆角矩形的padding值,以及遮罩的颜色

4.2在代码中动态获取xml中设置的值

init {

//通过TypeArray 获取 xml 配置的属性

val ta = context.obtainStyledAttributes(attrs, R.styleable.RoundRectCoverView)

mPadding = ta.getDimension(R.styleable.RoundRectCoverView_roundPadding, 40.dp)

mRoundCorner = ta.getDimension(R.styleable.RoundRectCoverView_roundCorner, 10.dp)

mCoverColor = ta.getColor(R.styleable.RoundRectCoverView_roundCoverColor, "#99000000".toColorInt())

ta.recycle()

}

通过TypeArray获取,声明的属性值

赋值给成员变量,下面使用的时候就直接使用了

回收TypeArray

4.3在xml代码直接使用

xmlns:app="/apk/res-auto"

android:layout_width="match_parent"

android:layout_height="match_parent">

android:layout_width="0dp"

android:layout_height="0dp"

android:src="@drawable/captain_america"

android:scaleType="centerCrop"

app:layout_constraintBottom_toBottomOf="parent"

app:layout_constraintLeft_toLeftOf="parent"

app:layout_constraintRight_toRightOf="parent"

app:layout_constraintTop_toTopOf="parent" />

android:layout_width="0dp"

android:layout_height="0dp"

app:layout_constraintBottom_toBottomOf="parent"

app:layout_constraintLeft_toLeftOf="parent"

app:layout_constraintRight_toRightOf="parent"

app:layout_constraintTop_toTopOf="parent"

app:roundCorner="10dp"//角度

app:roundCoverColor="#aa000000"//遮罩颜色

app:roundPadding="30dp" />

5.总结

离屏缓冲的两种方式区别以及开启方式

Canvas.saveLayer() 可以做短时的离屏缓冲,Google不建议使用,因为每次绘制都需要拿出一块来,耗费性能

View.setLayerType()是直接把整个 View 都绘制在离屏缓冲中,Google建议这样做。setLayerType(LAYER_TYPE_HARDWARE) 是使用 GPU 来缓冲, setLayerType(LAYER_TYPE_SOFTWARE) 是直接直接用一个 Bitmap 来缓冲。

PorterDuff.Mode的类型,已经使用,需要有透明的背景色

自定义属性的方式

这是一个简单且使用的Demo,很适合练手!

6.源码地址

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。