布局透明形狀的view的做法

最近要弄一個透明的圓形的一個覆蓋view,這個平時做應用的時候經常需要用到。如下圖所示:

3.png

我想大多數人平時的用法就是要設計出一張這樣的圖片,這樣簡單省事,但是也有個難題就是這個圖片是死的,中間部分的透明圓不能移動。
我整理了下面的四種方法,

一、就是上面說的用圖片

這種方法就是圖片是死的不方便移動。

二、就是自己畫,(這種方式應該說是最簡單了,還可以隨心所欲的變動)

自定義一個透明背景的view,在view上畫出一個圓

下面說實現
4.png

如果你需要一個半徑為b的透明圓,實現如下
首先定義畫筆Paint mPaint = new Paint();
然后定義你想要的顏色

mPaint.setAntiAlias(true);
mPaint.setColor(ContextCompat.getColor(context, R.color.jasper));
mPaint.setStyle(Paint.Style.STROKE);

再定義你畫筆的寬度mPaint.setStrokeWidth(a+b);
a是圓據頂部的高度,b是圓的半徑,實際上就是這個畫布高度的一半

重點來了

你如果就這么canvas.drawCircle(x, y, b, mPaint);畫圓,那你得到的圓的大小肯定不對,這個時候圓的半徑需要擴大,才能得到你想要的半徑是b的圓,那怎么擴大呢?
實際上就是將半徑的大小變?yōu)樵镜陌霃酱笮〖由袭嫻P寬度的一半。即 raduis=b + (a+b)/2
然后canvas.drawCircle(x, y, raduis, mPaint);這樣畫出的圓的半徑才是b。

這樣做的好處是你想將圓畫在哪里都可以,也可以是其他的任何形狀。

三、也是畫,根據網友說的,取path差集就可以

定義畫筆

val mPaint = Paint()
mPaint.isAntiAlias = true
mPaint.color = ContextCompat.getColor(context!!, R.color.colorWhite)
mPaint.style = Paint.Style.FILL
mPaint.strokeWidth = 5f

然后開畫,定義兩個path,mPath和mPath1.

var mPath = Path()
var mPath1 = Path()
val rectf = RectF(0F, 0F, getDisplayWidth().toFloat(), getDisplayHeight().toFloat())
mPath.addRect(rectf, Path.Direction.CW)
mPath1.addCircle(x, y, mRadius, Path.Direction.CW)
val path = mPath.minus(mPath1)//取差集
canvas?.drawPath(path, mPaint)

四、還是畫,這種方式復雜點

定義畫筆將圓之外的部分畫滿,留下圓不畫,那就是了。這需要用path實現。
首先一樣是定義畫筆

val mPaint = Paint()
mPaint.isAntiAlias = true
mPaint.color = ContextCompat.getColor(context!!, R.color.colorWhite)
mPaint.style = Paint.Style.FILL
mPaint.strokeWidth = 5f

隨后開始畫,例如我的圓心在寬度的中間,

mPath.moveTo(getDisplayWidth() / 2 - mRadius, mMarginTop + mRadius)//第一個點在圓心左側的邊緣
mPath.lineTo(0F, mMarginTop + mRadius)//第二個點橫移到最左側
mPath.lineTo(0F, 0F)//第三個點到屏幕左上角
mPath.lineTo((getDisplayWidth() / 2).toFloat(), 0F)//第四個點到圓心的正上方,屏幕的最頂端
mPath.lineTo((getDisplayWidth() / 2).toFloat(), mMarginTop.toFloat())//第五個點圓心上方,圓的邊緣
mPath.cubicTo((getDisplayWidth() / 2).toFloat(), mMarginTop.toFloat(),
            getDisplayWidth() / 2 - mRadius, mMarginTop.toFloat(),
            getDisplayWidth() / 2 - mRadius,
            mMarginTop + mRadius
        )//利用貝塞爾曲線來畫半圓
canvas?.drawPath(mPath, mPaint)

畫出來的效果

5.png

總共要畫四個這樣的部分,其實畫出來后也不是那么圓,還是要在變化在畫上一個稍微寬一點的圓,這比較麻煩,建議使用第二種。

四、其實還有一種方法,但是這種方法對布局有要求,有缺陷下面會講

比如我上一篇 一個非常好用的頁面引導工具guideView
這里面就是畫的一個透明的圖形。
首先是定義畫筆

mPaint.isAntiAlias = true
mPaint.style = Paint.Style.FILL_AND_STROKE
mPaint.xfermode = PorterDuffXfermode(PorterDuff.Mode.CLEAR)

然后直接畫出一想要的形狀即可canvas?.drawCircle(x,y,mRaduis,mPaint)
你還可以定義一個半透明的背景setBackgroundColor(ContextCompat.getColor(context!!, R.color.translucence))

這樣定義出來的view直接就有那個效果。但是這個view我直接放在layout中是不行的,畫出來的是一個黑色不透明的圖形,只有將這個view放在popupwindow或者dialog中時起作用。(這里目前我也不知道為什么,我嘗試將所有的activity都變成透明的背景,但還是一樣都是不起作用)

我想上面三種方法已經夠用了,晚點我打成一個庫,可以通過設置padding、margin、半徑、或者圖形選擇來畫出任何位置的任何圖形的透明圖片,現在沒時間,有個項目正在催。

好了,今天就到這里。上面的方法不滿意,請看下篇,絕對畫法,能支持到api14,包你滿意

?著作權歸作者所有,轉載或內容合作請聯系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

友情鏈接更多精彩內容