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="http://schemas.android.com/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.源碼地址
總結
以上是生活随笔為你收集整理的android 图片圆角 遮罩_Android 自定义View练手Demo(一)实现圆角遮罩效果的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 判断字符串 正则_(重学前端 - Jav
- 下一篇: python双引号报错_Python中s