轉(zhuǎn)載注明出處:http://www.lxweimin.com/p/818e1284158d
1. 概述
Android研發(fā)中經(jīng)常會遇見圓角或者圓形圖片的展示,但是系統(tǒng)中ImageView并不能直接支持,需要我們自己做一些處理,來實(shí)現(xiàn)圓角圖片或者圓形圖片,自己最近對這塊的實(shí)現(xiàn)做了一下總結(jié),看一下幾種實(shí)現(xiàn)方法。
- 圖層疊加,上層覆蓋一層蒙版,遮擋圖片,讓圖片展示出圓角或者圓形效果
- 重新繪制
- BitmapShader
- Xfermode
- RoundedBitmapDrawable
- CardView,使用官方控件,自動裁剪,達(dá)到圓角或者圓形效果。(5.0以上系統(tǒng))
第一種方法,很傻,不太優(yōu)雅,不推薦這種方法,了解這種方法是因?yàn)榇_實(shí)看見有人這么做過。推薦使用第二種方法,重新繪制圖片,不僅可以繪制出四角圓角圖片,還可以繪制出底部/頂部/左邊/右邊圓角效果,非常方便。如果想要偷懶,可以直接使用RoundedBitmapDrawable來實(shí)現(xiàn)圓角照片效果。而第三種方法,使用CardView
控件有很大的局限性,它只在5.0以及以上的系統(tǒng)中有效。
下面就來看一下各種方法的具體情況吧。
2. 圖層疊加
圖層疊加原理很簡單,就是在一張圖片上面疊加一層圖,覆蓋部分,讓圖片展示成圓角。具體原理可以參考下面這張圖。
看一下布局代碼,很簡單。
<?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>
運(yùn)行結(jié)果如下:
效果還是可以的,但是缺點(diǎn)也很明顯,一是要準(zhǔn)備兩張圖片,會增加額外的包體積;二是圖片疊加一起,必然導(dǎo)致過度繪制;三是該方法太死板,使用時(shí)候要考慮圖片大小,控件大小,以及蒙層圖圓角鋸齒效果,非常不靈活,Java里面不靈活就意味著可用性不強(qiáng)。
所以這種方法不建議使用,大家作為了解就行。提出這種方法是為了讓大家了解一下圖層,后面重新繪制過程中,有一種方法邏輯跟這個相似,也是繪制圖層疊加,生成圓角圖片。
3. 重新繪制
對圖片的繪制要特別的注意,有時(shí)候可能圖片太大需要我們壓縮,關(guān)于圖片壓縮大家可以查看這片文章壓縮圖片。重新繪制圖片,將圖片繪制成圓角,有三種方法。
- 使用BitmapShader
- 使用Xfermode
- 使用RoundedBitmapDrawable
從性能上講并沒有太大的區(qū)別,但是從使用靈活性上說,個人推薦使用BitmapShader。
在介紹這三個方法之前,先介紹一下圖片的拉伸縮放適配,大多數(shù)情況先,要展示圖片的控件(ImageView)的長寬和圖片的長寬并不是一致的,甚至長寬比都不一致,所以在拿到一張圖片時(shí)候,大多數(shù)情況下需要根據(jù)控件的大小對圖片進(jìn)行拉伸縮放處理,有人會問為什么不直接使用ImageView
屬性scaleType
去控制拉伸縮放,這是因?yàn)楫?dāng)我們將一個Bitmap繪制成圓角后,再去進(jìn)行拉伸縮放,圓角可能會變形,所以在Bitmap設(shè)置到控件之前就需要對Bitmap進(jìn)行一下拉伸縮放處理,直接看下面代碼。
// 圖片根據(jù)控件大小等比例縮放拉伸
float widthScale = imageViewWidth * 1.0f / bitmap.getWidth();
float heightScale = imageViewHeight * 1.0f / bitmap.getHeight();
// 設(shè)置長寬拉伸縮放比
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繪制圓角
所有的繪制圓角的實(shí)現(xiàn),推薦使用這個方法,不僅僅可以幫助我們實(shí)現(xiàn)圓角,連部分圓角都可以實(shí)現(xiàn),比如頂部是兩個圓角,底部是兩個直角的圖片。
首先介紹一下BitmapShader
這個類,它作為紋理用于繪制一張圖。新圖可以是紋理圖重復(fù)/鏡像/邊緣像素拉伸而繪制成的新圖。這個類構(gòu)造函數(shù)很簡單,BitmapShader(Bitmap bitmap, TileMode tileX, TileMode tileY)
,第一個參數(shù)是Bitmap,作為紋理圖傳入,tileX是指在水平方向上的繪制方式,tileY是指在豎直方向上的繪制方式。TileMode
有三種屬性,拉伸、重復(fù)、鏡像。
- TileMode.CLAMP 拉伸繪制,并不是指圖片拉伸,而是指圖片最后一個像素不斷繪制,紋理圖水平或者豎直方向最后一個像素不斷繪制
- TileMode.REPEAT 重復(fù)繪制,在水平或者豎直方向上不斷重復(fù)繪制紋理圖
- TileMode.MIRROR 鏡像繪制,水平或者豎直方向不斷的繪制翻轉(zhuǎn)紋理圖
使用BitmapShader繪制圖的時(shí)候,是從畫布的左上角開始繪制的。我們是使用拉伸的繪制模式,直接來看一下代碼,了解處理過程。
/**
* 利用BitmapShader繪制圓角圖片
*
* @param bitmap
* 待處理圖片
* @param outWidth
* 結(jié)果圖片寬度,一般為控件的寬度
* @param outHeight
* 結(jié)果圖片高度,一般為控件的高度
* @param radius
* 圓角半徑大小
* @return
* 結(jié)果圖片
*/
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);
// 根據(jù)控件大小對紋理圖進(jìn)行拉伸縮放處理
bitmapShader.setLocalMatrix(matrix);
// 初始化目標(biāo)bitmap
Bitmap targetBitmap = Bitmap.createBitmap(outWidth, outHeight, Bitmap.Config.ARGB_8888);
// 初始化目標(biāo)畫布
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;
}
首先初始化了繪制的紋理圖,并對圖片進(jìn)行了拉伸縮放處理,沒有用到上面提及的拉伸縮放處理方法是因?yàn)锽itmapShader本身自帶了這個屬性,進(jìn)行設(shè)置即可。然后初始化了畫布和畫筆,將設(shè)置畫筆繪制的紋理圖,畫筆在繪制圖形時(shí)候就不是使用單純的顏色繪制了。最后在利用畫筆在畫布上面繪制出圓形圖片。
看一下這個方法Canvas.drawRoundRect(RectF rect, float rx, float ry, Paint paint)
,第一個參數(shù)是指定畫布的繪制區(qū)域,從畫布的左上角開始計(jì)算;第二個第三個參數(shù)是圓角的x軸/y軸的繪制半徑,一般設(shè)置成相同的值;第三個就是畫筆。
我們看一下運(yùn)行效果。
看起來很簡單,但這并不是我推薦使用這種方法的原因,豐富的繪制結(jié)果才是,有很多樣式可以繪制,講一個比較簡單的,底部兩個圓角,頂部兩個直角,看一下運(yùn)行效果圖。
已經(jīng)感覺有點(diǎn)厲害了,先來看代碼的實(shí)現(xiàn)。
/**
* 利用BitmapShader繪制底部圓角圖片
*
* @param bitmap
* 待處理圖片
* @param outWidth
* 結(jié)果圖片寬度,一般為控件的寬度
* @param outHeight
* 結(jié)果圖片高度,一般為控件的高度
* @param radius
* 圓角半徑大小
* @return
* 結(jié)果圖片
*/
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);
// 根據(jù)控件大小對紋理圖進(jìn)行拉伸縮放處理
bitmapShader.setLocalMatrix(matrix);
// 初始化目標(biāo)bitmap
Bitmap targetBitmap = Bitmap.createBitmap(outWidth, outHeight, Bitmap.Config.ARGB_8888);
// 初始化目標(biāo)畫布
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;
}
仔細(xì)的同學(xué)已經(jīng)發(fā)現(xiàn)了,這部分代碼和上面很相似,只不過最后兩句有些不同。對,因?yàn)楹竺鎯删涫菍D片的繪制,最后輸出我們想要的效果。targetCanvas.drawRoundRect()
先在底部繪制出圓角的矩形,然后targetCanvas.drawRect()
繪制出上面的直角。targetCanvas.drawRoundRect()
它在畫布上面繪制了圖片底部2*radius
高度的部分,繪制出的結(jié)果是一個高度為2*radius
的圓角圖片,然后再在畫布0到outHeight - radius
部分繪制出一個直角矩形,這個直角矩形正好覆蓋了之前繪制的圓角圖片的上半部分,只露出下面的圓角,此時(shí)畫布上面呈現(xiàn)出的圖像就是剛才運(yùn)行的效果圖,看一下下面的原理圖幫助我們理解一下。
是不是有點(diǎn)類似上面提高的圖層疊加的原理了,根據(jù)各種疊加情況,可以繪制出多種效果,有下面幾種(同一個圖中圓角半徑都相同):
- 四角都是圓角
- 同邊圓角,底部圓角/頂部圓角/左邊圓角/右邊圓角
- 對角線圓角,左上右下圓角/左下右上圓角
- 單個圓角,左上圓角/左下圓角/右上圓角/右下圓角
- 三個圓角,左上非圓角/左下非圓角/右上非圓角/右下非圓角
除了這些繪制效果,我們還可以繪制出圓角半徑不同的圖,在此不做討論。上述所有的繪制代碼在后面會給出工程地址,或者直接點(diǎn)擊這里查看。
3.2 Xfermode繪制圓角
在使用畫筆Paint去繪制東西,當(dāng)繪制多個圖層疊加的時(shí)候,有16中模式。效果如下圖。
模式 | 說明 |
---|---|
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 | 取兩圖層全部區(qū)域,交集部分變?yōu)橥该魃?/td> |
官方demo中主要繪制代碼如下:
// mDstB是黃色的圓形圖bitmap
// mSrcB是藍(lán)色的矩形圖bitmap
canvas.drawBitmap(mDstB, 0, 0, paint);
paint.setXfermode(sModes[i]);
canvas.drawBitmap(mSrcB, 0, 0, paint)
可以看到在兩個繪制圖形過程中,添加Xfermode繪制模式,能夠改變兩個圖的疊加效果,我們主要關(guān)注一下SrcIn
模式,可以看見,用圖層疊加的交集去截取mSrcB
圖,可以利用這個,想繪制一個圓角的圖,然后設(shè)置繪制模式,接著繪制一個矩形的圖,兩者一疊加,正好是用圓角圖去截取矩形圖,矩形圖也就是我們的原圖片了。
直接看一下實(shí)現(xiàn)代碼。
/**
* 利用Xfermode繪制圓角圖片
*
* @param bitmap
* 待處理圖片
* @param outWidth
* 結(jié)果圖片寬度,一般為控件的寬度
* @param outHeight
* 結(jié)果圖片高度,一般為控件的高度
* @param radius
* 圓角半徑大小
* @return
* 結(jié)果圖片
*/
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);
// 初始化目標(biāo)bitmap
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);
// 設(shè)置疊加模式
paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
// 在畫布上繪制原圖片
Rect ret = new Rect(0, 0, outWidth, outHeight);
canvas.drawBitmap(newBt, ret, ret, paint);
return targetBitmap;
}
最后展示一下運(yùn)行的效果圖。
3.3 RoundedBitmapDrawable繪制圓角
如果你覺得上面兩種方法還是好麻煩,肯本不想去搞這些繪制的東西,有沒有簡單的方法呢?
有!
在V4包中有一個RoundedBitmapDrawable
類,專門幫助實(shí)現(xiàn)圓角效果。
用法也很簡單,看代碼。
/**
* 利用RoundedBitmapDrawable繪制圓角圖片
*
* @param bitmap
* 待處理圖片
* @param outWidth
* 結(jié)果圖片寬度,一般為控件的寬度
* @param outHeight
* 結(jié)果圖片高度,一般為控件的高度
* @param radius
* 圓角半徑大小
* @return
* 結(jié)果圖片
*/
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;
}
代碼就是三行,初始化,然后設(shè)置圓角半徑dr.setCornerRadius()
,設(shè)置邊緣平滑dr.setAntiAlias()
(這步可以不需要)。運(yùn)行效果如下。
其實(shí)去查看dr.setCornerRadius()
源代碼,會發(fā)現(xiàn)它內(nèi)部就是使用的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();
}
4. CardView控件圓角
CardView是官方在V7包中新增的一個控件,繼承FrameLayout
布局,擁有圓角和陰影屬性的控件,既然是新控件,看一下它的一些屬性。
- cardElevation 陰影的大小
- cardMaxElevation 陰影最大高度
- cardBackgroundColor 卡片的背景色
- cardCornerRadius 卡片的圓角大小
- contentPadding 卡片內(nèi)容于邊距的間隔
- contentPaddingBottom
- contentPaddingTop
- contentPaddingLeft
- contentPaddingRight
- contentPaddingStart
- contentPaddingEnd
- cardUseCompatPadding 設(shè)置內(nèi)邊距,V21+的版本和之前的版本仍舊具有一樣的計(jì)算方式
- cardPreventConrerOverlap 在V20和之前的版本中添加內(nèi)邊距,這個屬性為了防止內(nèi)容和邊角的
比較關(guān)注的是cardCornerRadius
和cardElevation
這兩個屬性,為了實(shí)現(xiàn)圓角圖片的效果,將cardElevation
屬性也就是陰影效果,設(shè)置為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
控件??匆幌逻\(yùn)行效果。
這個控件用起來非常偷懶,可惜的是CardView
調(diào)用了View的setClipToOutline(true)
方法來裁邊,5.0一下的系統(tǒng)沒有這個API,也就是說,5.0以下的系統(tǒng)不會呈現(xiàn)出圓角。
雖然這個控件不能幫助我們實(shí)現(xiàn)圓角圖片的效果,但是給我們提供了一個圓角控件,也能幫助我們解決很多需求場景。
5. 圓形圖片的實(shí)現(xiàn)
了解了圓角照片的實(shí)現(xiàn),圓形照片的實(shí)現(xiàn)就很簡單了。圓形圖片需要的是一個正方形的圖片,將圓角半徑設(shè)置為正方形圖片邊長一半即可。但是有時(shí)候,我們拿到的圖片是一個矩形,長寬不一樣長!??!我們需要對圖片做裁剪處理,取矩形中間部分,讓它變成一個正方形圖片。
以BitmapShader
為例。
/**
* 利用BitmapShader繪制底部圓角圖片
*
* @param bitmap
* 待處理圖片
* @param edgeWidth
* 正方形控件大小
* @param radius
* 圓角半徑大小
* @return
* 結(jié)果圖片
*/
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;
}
// 設(shè)置拉伸縮放比
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);
// 初始化目標(biāo)bitmap
Bitmap targetBitmap = Bitmap.createBitmap(edgeWidth, edgeWidth, Bitmap.Config.ARGB_8888);
// 初始化目標(biāo)畫布
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;
}
裁剪拉伸的邏輯比較復(fù)雜,主要是因?yàn)閳D片長寬和正方形邊長各種關(guān)系復(fù)雜導(dǎo)致。將圖片處理成正方形圖片后,后面代碼和切圓角代碼基本類似。
- 如果矩形圖片的寬大于高,那么豎直方向上不需要裁剪,以矩形圖片高度為裁剪后的正方形的邊長,同時(shí)計(jì)算出水平方向上的裁剪位置
- 如果矩形圖片的高不小于寬,那么水平方向上不需要裁剪,以矩形圖片寬度為裁剪后的正方形的邊長,同時(shí)計(jì)算出豎直方向上的裁剪位置
- 最后計(jì)算出裁剪后的正方形圖邊長與控件邊長的拉伸縮放比例,因?yàn)槎际钦叫?,只需要?jì)算一邊的縮放比即可。
最后來看一下圓形圖片的實(shí)現(xiàn)效果。
看到這里你會發(fā)現(xiàn),其實(shí)圓形圖片的實(shí)現(xiàn)和圓角圖片的實(shí)現(xiàn)基本是相同的,了解圓角圖片的實(shí)現(xiàn)方法,圓形圖片的實(shí)現(xiàn)自然不在話下。
6. 總結(jié)
上述介紹了大概五種圓角圖片的實(shí)現(xiàn)方法,方法沒有優(yōu)劣,在具體的業(yè)務(wù)場景選擇最適合的方法才是最重要的,但是最為一個有追求的程序員,還是建議大家多了解重新繪制里面的幾種方法。
最后附上Demo工程的地址:地址鏈接,里面包含了利用BitmapShader
繪制多種效果的單例類RoundBitmapTransformation
。在寫demo過程中,因?yàn)槭褂玫膱D片太大,有出現(xiàn)OOM的異常,如果覺得圖片太大,你可以替換掉Demo工程中的圖片,其實(shí)在實(shí)際中對圖片操作也很容易引起OOM,關(guān)于圖片的壓縮處理,大家可以參考這篇文章。