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>
-
1
-
2
-
3
-
4
-
5
-
6
-
7
-
8
-
9
-
10
-
11
-
12
-
13
-
14
-
15
-
16
-
17
-
18
-
19
-
20
-
1
-
2
-
3
-
4
-
5
-
6
-
7
-
8
-
9
-
10
-
11
-
12
-
13
-
14
-
15
-
16
-
17
-
18
-
19
-
20
運行結果如下:

圖-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 拉伸繪制,并不是指圖片拉伸,而是指圖片后一個像素不斷繪制,紋理圖水平或者豎直方向后一個像素不斷繪制
-
TileMode.REPEAT 重復繪制,在水平或者豎直方向上不斷重復繪制紋理圖
-
TileMode.MIRROR 鏡像繪制,水平或者豎直方向不斷的繪制翻轉紋理圖
使用BitmapShader繪制圖的時候,是從畫布的左上角開始繪制的。我們是使用拉伸的繪制模式,直接來看一下代碼,了解處理過程。
/**
* 利用BitmapShader繪制圓角圖片
*
* @param bitmap
* 待處理圖片
* @param outWidth
* 結果圖片寬度,一般為控件的寬度
* @param outHeight
* 結果圖片高度,一般為控件的高度
* @param radius
* 圓角半徑大小
* @return * 結果圖片
*/ private Bitmap roundBitmapByShader(Bitmap bitmap, int outWidth, int outHeight, int radius) { if(bitmap == null) { throw new NullPointerException("Bitmap can't be null");
} float widthScale = outWidth * 1.0f / bitmap.getWidth(); float heightScale = outHeight * 1.0f / bitmap.getHeight();
Matrix matrix = new Matrix();
matrix.setScale(widthScale, heightScale); BitmapShader bitmapShader = new BitmapShader(bitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP); bitmapShader.setLocalMatrix(matrix); Bitmap targetBitmap = Bitmap.createBitmap(outWidth, outHeight, Bitmap.Config.ARGB_8888); Canvas targetCanvas = new Canvas(targetBitmap); Paint paint = new Paint();
paint.setAntiAlias(true);
paint.setShader(bitmapShader); targetCanvas.drawRoundRect(new RectF(0, 0, outWidth, outWidth), radius, radius, paint); return targetBitmap;
}
-
1
-
2
-
3
-
4
-
5
-
6
-
7
-
8
-
9
-
10
-
11
-
12
-
13
-
14
-
15
-
16
-
17
-
18
-
19
-
20
-
21
-
22
-
23
-
24
-
25
-
26
-
27
-
28
-
29
-
30
-
31
-
32
-
33
-
34
-
35
-
36
-
37
-
38
-
39
-
40
-
41
-
42
-
43
-
44
-
45
-
1
-
2
-
3
-
4
-
5
-
6
-
7
-
8
-
9
-
10
-
11
-
12
-
13
-
14
-
15
-
16
-
17
-
18
-
19
-
20
-
21
-
22
-
23
-
24
-
25
-
26
-
27
-
28
-
29
-
30
-
31
-
32
-
33
-
34
-
35
-
36
-
37
-
38
-
39
-
40
-
41
-
42
-
43
-
44
-
45
首先初始化了繪制的紋理圖,并對圖片進行了拉伸縮放處理,沒有用到上面提及的拉伸縮放處理方法是因為BitmapShader本身自帶了這個屬性,進行設置即可。然后初始化了畫布和畫筆,將設置畫筆繪制的紋理圖,畫筆在繪制圖形時候就不是使用單純的顏色繪制了。后在利用畫筆在畫布上面繪制出圓形圖片。
看一下這個方法Canvas.drawRoundRect(RectF rect, float rx, float ry, Paint paint),個參數是指定畫布的繪制區域,從畫布的左上角開始計算;第二個第三個參數是圓角的x軸/y軸的繪制半徑,一般設置成相同的值;第三個就是畫筆。
我們看一下運行效果。

圖-3 BitmapShader圓角效果圖
看起來很簡單,但這并不是我推薦使用這種方法的原因,豐富的繪制結果才是,有很多樣式可以繪制,講一個比較簡單的,底部兩個圓角,頂部兩個直角,看一下運行效果圖。
我們看一下運行效果。

圖-4 BitmapShader底部圓角效果圖
已經感覺有點厲害了,先來看代碼的實現。
/**
* 利用BitmapShader繪制底部圓角圖片
*
* @param bitmap
* 待處理圖片
* @param outWidth
* 結果圖片寬度,一般為控件的寬度
* @param outHeight
* 結果圖片高度,一般為控件的高度
* @param radius
* 圓角半徑大小
* @return * 結果圖片
*/ private Bitmap roundBottomBitmapByShader(Bitmap bitmap, int outWidth, int outHeight, int radius) { if(bitmap == null) { throw new NullPointerException("Bitmap can't be null");
} float widthScale = outWidth * 1.0f / bitmap.getWidth(); float heightScale = outHeight * 1.0f / bitmap.getHeight();
Matrix matrix = new Matrix();
matrix.setScale(widthScale, heightScale); BitmapShader bitmapShader = new BitmapShader(bitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP); bitmapShader.setLocalMatrix(matrix); Bitmap targetBitmap = Bitmap.createBitmap(outWidth, outHeight, Bitmap.Config.ARGB_8888); Canvas targetCanvas = new Canvas(targetBitmap); Paint paint = new Paint();
paint.setAntiAlias(true);
paint.setShader(bitmapShader); targetCanvas.drawRoundRect(new RectF(0, outHeight - 2 * radius, outWidth, outWidth), radius, radius, paint); targetCanvas.drawRect(new RectF(0, 0, outWidth, outHeight - radius), paint); return targetBitmap;
}
-
1
-
2
-
3
-
4
-
5
-
6
-
7
-
8
-
9
-
10
-
11
-
12
-
13
-
14
-
15
-
16
-
17
-
18
-
19
-
20
-
21
-
22
-
23
-
24
-
25
-
26
-
27
-
28
-
29
-
30
-
31
-
32
-
33
-
34
-
35
-
36
-
37
-
38
-
39
-
40
-
41
-
42
-
43
-
44
-
45
-
46
-
47
-
48
-
1
-
2
-
3
-
4
-
5
-
6
-
7
-
8
-
9
-
10
-
11
-
12
-
13
-
14
-
15
-
16
-
17
-
18
-
19
-
20
-
21
-
22
-
23
-
24
-
25
-
26
-
27
-
28
-
29
-
30
-
31
-
32
-
33
-
34
-
35
-
36
-
37
-
38
-
39
-
40
-
41
-
42
-
43
-
44
-
45
-
46
-
47
-
48
仔細的同學已經發現了,這部分代碼和上面很相似,只不過后兩句有些不同。對,因為后面兩句是對圖片的繪制,后輸出我們想要的效果。targetCanvas.drawRoundRect()先在底部繪制出圓角的矩形,然后targetCanvas.drawRect()繪制出上面的直角。targetCanvas.drawRoundRect()它在畫布上面繪制了圖片底部2*radius高度的部分,繪制出的結果是一個高度為2*radius的圓角圖片,然后再在畫布0到outHeight - radius部分繪制出一個直角矩形,這個直角矩形正好覆蓋了之前繪制的圓角圖片的上半部分,只露出下面的圓角,此時畫布上面呈現出的圖像就是剛才運行的效果圖,看一下下面的原理圖幫助我們理解一下。
我們看一下運行效果。

圖-5 Bitmapshader底部圓角原理
是不是有點類似上面提高的圖層疊加的原理了,根據各種疊加情況,可以繪制出多種效果,有下面幾種(同一個圖中圓角半徑都相同):
-
四角都是圓角
-
同邊圓角,底部圓角/頂部圓角/左邊圓角/右邊圓角
-
對角線圓角,左上右下圓角/左下右上圓角
-
單個圓角,左上圓角/左下圓角/右上圓角/右下圓角
-
三個圓角,左上非圓角/左下非圓角/右上非圓角/右下非圓角
除了這些繪制效果,我們還可以繪制出圓角半徑不同的圖,在此不做討論。上述所有的繪制代碼在后面會給出工程地址,或者直接點擊這里查看。
3.2 Xfermode繪制圓角
在使用畫筆Paint去繪制東西,當繪制多個圖層疊加的時候,有16中模式。效果如下圖。

圖-6 Xfermode類型效果圖
|
模式
|
說明
|
|
PorterDuff.Mode.CLEAR
|
所有繪制不會繪制到畫布上
|
|
PorterDuff.Mode.SRC
|
顯示上層繪制圖形
|
|
PorterDuff.Mode.DST
|
顯示下層繪制圖形
|
|
PorterDuff.Mode.SRC_OVER
|
圖形疊加,上層蓋住下層
|
|
PorterDuff.Mode.DST_OVER
|
圖形疊加,下層蓋住上層
|
|
PorterDuff.Mode.SRC_IN
|
顯示上層交集部分
|
|
PorterDuff.Mode.DST_IN
|
顯示下層交集部分
|
|
PorterDuff.Mode.SRC_OUT
|
顯示上層非交集部分
|
|
PorterDuff.Mode.DST_OUT
|
顯示下層非交集部分
|
|
PorterDuff.Mode.SRC_ATOP
|
顯示下層非交集部分和上層交集部分
|
|
PorterDuff.Mode.DST_ATOP
|
顯示下層交集部分與上層非交集部分
|
|
PorterDuff.Mode.XOR
|
去除交集部分
|
|
PorterDuff.Mode.DARKEN
|
交集部分顏色加深
|
|
PorterDuff.Mode.LIGHTEN
|
交集部分顏色變亮
|
|
PorterDuff.Mode.MULTIPLY
|
顯示交集部分,顏色混合疊加
|
|
PorterDuff.Mode.SCREEN
|
取兩圖層全部區域,交集部分變為透明色
|
官方demo中主要繪制代碼如下:
canvas.drawBitmap(mDstB, 0, 0, paint);
paint.setXfermode(sModes[i]);
canvas.drawBitmap(mSrcB, 0, 0, paint)
可以看到在兩個繪制圖形過程中,添加Xfermode繪制模式,能夠改變兩個圖的疊加效果,我們主要關注一下SrcIn模式,可以看見,用圖層疊加的交集去截取mSrcB圖,可以利用這個,想繪制一個圓角的圖,然后設置繪制模式,接著繪制一個矩形的圖,兩者一疊加,正好是用圓角圖去截取矩形圖,矩形圖也就是我們的原圖片了。
直接看一下實現代碼。
/**
* 利用Xfermode繪制圓角圖片
*
* @param bitmap
* 待處理圖片
* @param outWidth
* 結果圖片寬度,一般為控件的寬度
* @param outHeight
* 結果圖片高度,一般為控件的高度
* @param radius
* 圓角半徑大小
* @return * 結果圖片
*/ private Bitmap roundBitmapByXfermode(Bitmap bitmap, int outWidth, int outHeight, int radius) { if(bitmap == null) { throw new NullPointerException("Bitmap can't be null");
} float widthScale = outWidth * 1.0f / bitmap.getWidth(); float heightScale = outHeight * 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); Bitmap targetBitmap = Bitmap.createBitmap(outWidth, outHeight, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(targetBitmap);
canvas.drawARGB(0, 0, 0, 0);
Paint paint = new Paint();
paint.setAntiAlias(true);
RectF rectF = new RectF(0f, 0f, (float) outWidth, (float) outHeight); canvas.drawRoundRect(rectF, radius, radius, paint); paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN)); Rect ret = new Rect(0, 0, outWidth, outHeight);
canvas.drawBitmap(newBt, ret, ret, paint); return targetBitmap;
}
-
1
-
2
-
3
-
4
-
5
-
6
-
7
-
8
-
9
-
10
-
11
-
12
-
13
-
14
-
15
-
16
-
17
-
18
-
19
-
20
-
21
-
22
-
23
-
24
-
25
-
26
-
27
-
28
-
29
-
30
-
31
-
32
-
33
-
34
-
35
-
36
-
37
-
38
-
39
-
40
-
41
-
42
-
43
-
44
-
45
-
46
-
47
-
48
-
49
-
1
-
2
-
3
-
4
-
5
-
6
-
7
-
8
-
9
-
10
-
11
-
12
-
13
-
14
-
15
-
16
-
17
-
18
-
19
-
20
-
21
-
22
-
23
-
24
-
25
-
26
-
27
-
28
-
29
-
30
-
31
-
32
-
33
-
34
-
35
-
36
-
37
-
38
-
39
-
40
-
41
-
42
-
43
-
44
-
45
-
46
-
47
-
48
-
49
后展示一下運行的效果圖。

圖-7 Xfermode圓角效果圖
3.3 RoundedBitmapDrawable繪制圓角
如果你覺得上面兩種方法還是好麻煩,肯本不想去搞這些繪制的東西,有沒有簡單的方法呢?
有!
在V4包中有一個RoundedBitmapDrawable類,專門幫助實現圓角效果。
用法也很簡單,看代碼。
/**
* 利用RoundedBitmapDrawable繪制圓角圖片
*
* @param bitmap
* 待處理圖片
* @param outWidth
* 結果圖片寬度,一般為控件的寬度
* @param outHeight
* 結果圖片高度,一般為控件的高度
* @param radius
* 圓角半徑大小
* @return * 結果圖片
*/ private Drawable roundBitmapByBitmapDrawable(Bitmap bitmap, int outWidth, int outHeight, int radius) { if(bitmap == null) { throw new NullPointerException("Bitmap can't be null");
} float widthScale = outWidth * 1.0f / bitmap.getWidth(); float heightScale = outHeight * 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); RoundedBitmapDrawable dr = RoundedBitmapDrawableFactory.create(getResources(), newBt);
dr.setCornerRadius(radius);
dr.setAntiAlias(true); return dr;
}
-
1
-
2
-
3
-
4
-
5
-
6
-
7
-
8
-
9
-
10
-
11
-
12
-
13
-
14
-
15
-
16
-
17
-
18
-
19
-
20
-
21
-
22
-
23
-
24
-
25
-
26
-
27
-
28
-
29
-
30
-
31
-
32
-
33
-
1
-
2
-
3
-
4
-
5
-
6
-
7
-
8
-
9
-
10
-
11
-
12
-
13
-
14
-
15
-
16
-
17
-
18
-
19
-
20
-
21
-
22
-
23
-
24
-
25
-
26
-
27
-
28
-
29
-
30
-
31
-
32
-
33
代碼就是三行,初始化,然后設置圓角半徑dr.setCornerRadius(),設置邊緣平滑dr.setAntiAlias()(這步可以不需要)。運行效果如下。

圖-8 RoundedBitmapDrawable圓角效果圖
其實去查看dr.setCornerRadius()源代碼,會發現它內部就是使用的BitmapShader來繪制圓角效果。官方做了一層封裝,使得我們使用起來更加方便。
public void setCornerRadius(float cornerRadius) { if (mCornerRadius == cornerRadius) return;
mIsCircular = false; if (isGreaterThanZero(cornerRadius)) {
mPaint.setShader(mBitmapShader);
} else {
mPaint.setShader(null);
}
mCornerRadius = cornerRadius;
invalidateSelf();
}
-
1
-
2
-
3
-
4
-
5
-
6
-
7
-
8
-
9
-
10
-
11
-
12
-
13
-
1
-
2
-
3
-
4
-
5
-
6
-
7
-
8
-
9
-
10
-
11
-
12
-
13
4. CardView控件圓角
CardView是官方在V7包中新增的一個控件,繼承FrameLayout布局,擁有圓角和陰影屬性的控件,既然是新控件,看一下它的一些屬性。
-
cardElevation 陰影的大小
-
cardMaxElevation 陰影大高度
-
cardBackgroundColor 卡片的背景色
-
cardCornerRadius 卡片的圓角大小
-
contentPadding 卡片內容于邊距的間隔
-
contentPaddingBottom
-
contentPaddingTop
-
contentPaddingLeft
-
contentPaddingRight
-
contentPaddingStart
-
contentPaddingEnd
-
cardUseCompatPadding 設置內邊距,V21+的版本和之前的版本仍舊具有一樣的計算方式
-
cardPreventConrerOverlap 在V20和之前的版本中添加內邊距,這個屬性為了防止內容和邊角的
比較關注的是cardCornerRadius和cardElevation這兩個屬性,為了實現圓角圖片的效果,將cardElevation屬性也就是陰影效果,設置為0dp,看一下具體的布局文件代碼。
<android.support.v7.widget.CardView android:layout_width="@dimen/round_bitmap_width" android:layout_height="@dimen/round_bitmap_width" app:cardCornerRadius="5dp" app:cardElevation="0dp"> <ImageView android:layout_width="match_parent" android:layout_height="match_parent" android:scaleType="fitXY" android:src="@drawable/demo_icon_android_logo"/> </android.support.v7.widget.CardView>
將CardView作為父布局,容納ImageView控件。看一下運行效果。

圖-9 CardView圓角效果圖-5.0系統
這個控件用起來非常偷懶,可惜的是CardView調用了View的setClipToOutline(true)方法來裁邊,5.0一下的系統沒有這個API,也就是說,5.0以下的系統不會呈現出圓角。

圖-10 CardView圓角效果圖-4.4系統
雖然這個控件不能幫助我們實現圓角圖片的效果,但是給我們提供了一個圓角控件,也能幫助我們解決很多需求場景。
5. 圓形圖片的實現
了解了圓角照片的實現,圓形照片的實現就很簡單了。圓形圖片需要的是一個正方形的圖片,將圓角半徑設置為正方形圖片邊長一半即可。但是有時候,我們拿到的圖片是一個矩形,長寬不一樣長!!!我們需要對圖片做裁剪處理,取矩形中間部分,讓它變成一個正方形圖片。
以BitmapShader為例。
/**
* 利用BitmapShader繪制底部圓角圖片
*
* @param bitmap
* 待處理圖片
* @param edgeWidth
* 正方形控件大小
* @param radius
* 圓角半徑大小
* @return * 結果圖片
*/ private Bitmap circleBitmapByShader(Bitmap bitmap, int edgeWidth, int radius) { if(bitmap == null) { throw new NullPointerException("Bitmap can't be null");
} float btWidth = bitmap.getWidth(); float btHeight = bitmap.getHeight(); float btWidthCutSite = 0; float btHeightCutSite = 0; float squareWidth = 0f; if(btWidth > btHeight) { btWidthCutSite = (btWidth - btHeight) / 2f;
squareWidth = btHeight;
} else { btHeightCutSite = (btHeight - btWidth) / 2f;
squareWidth = btWidth;
} float scale = edgeWidth * 1.0f / squareWidth;
Matrix matrix = new Matrix();
matrix.setScale(scale, scale); Bitmap squareBt = Bitmap.createBitmap(bitmap, (int)btWidthCutSite, (int)btHeightCutSite, (int)squareWidth, (int)squareWidth, matrix, true); BitmapShader bitmapShader = new BitmapShader(squareBt, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP); Bitmap targetBitmap = Bitmap.createBitmap(edgeWidth, edgeWidth, Bitmap.Config.ARGB_8888); Canvas targetCanvas = new Canvas(targetBitmap); Paint paint = new Paint();
paint.setAntiAlias(true);
paint.setShader(bitmapShader); targetCanvas.drawRoundRect(new RectF(0, 0, edgeWidth, edgeWidth), radius, radius, paint); return targetBitmap;
}
-
1
-
2
-
3
-
4
-
5
-
6
-
7
-
8
-
9
-
10
-
11
-
12
-
13
-
14
-
15
-
16
-
17
-
18
-
19
-
20
-
21
-
22
-
23
-
24
-
25
-
26
-
27
-
28
-
29
-
30
-
31
-
32
-
33
-
34
-
35
-
36
-
37
-
38
-
39
-
40
-
41
-
42
-
43
-
44
-
45
-
46
-
47
-
48
-
49
-
50
-
51
-
52
-
53
-
54
-
55
-
56
-
57
-
58
-
59
-
60
-
1
-
2
-
3
-
4
-
5
-
6
-
7
-
8
-
9
-
10
-
11
-
12
-
13
-
14
-
15
-
16
-
17
-
18
-
19
-
20
-
21
-
22
-
23
-
24
-
25
-
26
-
27
-
28
-
29
-
30
-
31
-
32
-
33
-
34
-
35
-
36
-
37
-
38
-
39
-
40
-
41
-
42
-
43
-
44
-
45
-
46
-
47
-
48
-
49
-
50
-
51
-
52
-
53
-
54
-
55
-
56
-
57
-
58
-
59
-
60
裁剪拉伸的邏輯比較復雜,主要是因為圖片長寬和正方形邊長各種關系復雜導致。將圖片處理成正方形圖片后,后面代碼和切圓角代碼基本類似。
-
如果矩形圖片的寬大于高,那么豎直方向上不需要裁剪,以矩形圖片高度為裁剪后的正方形的邊長,同時計算出水平方向上的裁剪位置
-
如果矩形圖片的高不小于寬,那么水平方向上不需要裁剪,以矩形圖片寬度為裁剪后的正方形的邊長,同時計算出豎直方向上的裁剪位置
-
后計算出裁剪后的正方形圖邊長與控件邊長的拉伸縮放比例,因為都是正方形,只需要計算一邊的縮放比即可。
后來看一下圓形圖片的實現效果。

圖-11 BitmapShader圓形效果圖
看到這里你會發現,其實圓形圖片的實現和圓角圖片的實現基本是相同的,了解圓角圖片的實現方法,圓形圖片的實現自然不在話下。
本站文章版權歸原作者及原出處所有 。內容為作者個人觀點, 并不代表本站贊同其觀點和對其真實性負責,本站只提供參考并不構成任何投資及應用建議。本站是一個個人學習交流的平臺,網站上部分文章為轉載,并不用于任何商業目的,我們已經盡可能的對作者和來源進行了通告,但是能力有限或疏忽,造成漏登,請及時聯系我們,我們將根據著作權人的要求,立即更正或者刪除有關內容。本站擁有對此聲明的最終解釋權。