android圖片圓角怎麼簡單高效實現?

android 圖片圓角要怎麼搞? 有沒有一個簡單且高效的方法------比如用cardview或樣式直接實現。代碼實現的圓角當大量圖片時會不會很慢?


佔位……到時回答。

好了,健身回來洗了個澡,目前12:40

圖片圓角實現,通過Canvas類中的drawRoundRect()方法:

這裡的參數:

rect:

可見上圖rect傳入RectF作為參數(RectF中的「F」表示接受的值是Float)

RectF類包含一個矩形的四個單精度浮點坐標。矩形通過上下左右4個邊的坐標來表示一個矩形

這裡的left、top、right、bottom的值意思是:

left:是矩形距離左邊的X軸

top:是矩形距離上邊的Y軸

right:是矩形距離右邊的X軸

bottom:是矩形距離下邊的Y軸

rx、ry:

x軸方向的圓角半徑,y軸方向的圓角半徑。

paint:

繪製時所使用的畫筆。

現在drawRoundRect()大概了解了,簡單的例子:

效果:

大概原理就是這些,知道原理後看看如何應用到主流圖片載入庫中:

目前主流的圖片載入庫主要有Picasso,Glide,Fresco,Android-Universal-Image-Loader等;

Picasso為例:

使用:

Glide和Picasso簡直一曲同工。這裡不再敘述:

最後

效果圖:

最後一點補充:

有評論說,我只想下面兩個角是圓角,上面保持不變好的滿足你,方法如下:

傳入的參數和上圖一樣:

使用和上面一樣,傳個定義好的枚舉類型

效果圖:

最後的最後再補充一點:

有人私信問我,為什麼不使用Fresco呢?

沒錯,Fresco很強大比Picasso、Glide都要強大,是Facebook的「黑科技」,但它的「侵入」感比較強,使用它,你必須將ImageView替換成com.facebook.drawee.view.SimpleDraweeView,如果項目工程剛開始搭建,並且項目中需要載入大量的圖片,那Fresco是個不錯的選擇,但是如果項目工程已經迭代了好幾個版本,布局中都替換成它還真是一個麻煩的事,所以我並不使用Fresco。

但Picasso、Glide就沒有這個問題,它們使用的還是ImageView控制項,所以我完全可以寫個ImageLoader工具類,所有的配置都寫在這裡,像下面這樣:

使用的時候,像這樣:

所有的地方都是統一調用的

ImageLoader.getInstance().displayImage(Context,ImageUrl,ImageView);

這樣其他地方並不修改,不管換什麼圖片載入框架,只要改ImageLoader里的實現就可以了

。。。。。。

最後的最後的最後再補充一點(這幾個載入圖片的庫都寫了,再問我可自殺了)

有人問,剛開始寫項目不想寫上面的方法,還有沒有簡單的方式去實現,有!大名鼎鼎的Fresco

GitHub - facebook/fresco: An Android library for managing images and the memory they use.

首先初始化

布局文件中配置

注意,SimpleDraweeView一定要確定具體的

roundedCornerRadius就是設置圓角的

更多設置:

具體意思去Github的項目主頁看中文文檔

使用setImageURI()載入圖片地址

效果圖:


最簡單的方法是在控制項的onDraw方法里用path截出一個圓角矩形,然後在再調super.ondraw,這樣就形成了一個圓角的控制項,而且可以是任意控制項


/**
* 矩形將圖片圓化
*
* @param bitmap
* 傳入Bitmap對象
* @return
*/
public Bitmap toRoundBitmap(Bitmap bitmap) {
int width = bitmap.getWidth();
int height = bitmap.getHeight();
float roundPx;
float left, top, right, bottom, dst_left, dst_top, dst_right, dst_bottom;
if (width &<= height) { roundPx = width / 2; left = 0; top = 0; right = width; bottom = width; height = width; dst_left = 0; dst_top = 0; dst_right = width; dst_bottom = width; } else { roundPx = height / 2; float clip = (width - height) / 2; left = clip; right = width - clip; top = 0; bottom = height; width = height; dst_left = 0; dst_top = 0; dst_right = height; dst_bottom = height; } Bitmap output = Bitmap.createBitmap(width, height, Config.ARGB_8888); Canvas canvas = new Canvas(output); final int color = 0xff424242; final Paint paint = new Paint(); final Rect src = new Rect((int) left, (int) top, (int) right, (int) bottom); final Rect dst = new Rect((int) dst_left, (int) dst_top, (int) dst_right, (int) dst_bottom); final RectF rectF = new RectF(dst); paint.setAntiAlias(true);// 設置畫筆無鋸齒 canvas.drawARGB(0, 0, 0, 0); // 填充整個Canvas paint.setColor(color); // 以下有兩種方法畫圓,drawRounRect和drawCircle // canvas.drawRoundRect(rectF, roundPx, roundPx, paint);// // 畫圓角矩形,第一個參數為圖形顯示區域,第二個參數和第三個參數分別是水平圓角半徑和垂直圓角半徑。 canvas.drawCircle(roundPx, roundPx, roundPx, paint); paint.setXfermode(new PorterDuffXfermode(Mode.SRC_IN));// 設置兩張圖片相交時的模式,參考http://trylovecatch.iteye.com/blog/1189452 canvas.drawBitmap(bitmap, src, dst, paint); // 以Mode.SRC_IN模式合併bitmap和已經draw了的Circle return output; }

/**
* 矩形將圖片的四角圓化
*
* @param bitmap
* 傳入Bitmap對象
* @return
*/
public static Bitmap getRoundedCornerBitmap(Bitmap bitmap) {
Bitmap output = Bitmap.createBitmap(bitmap.getWidth(),
bitmap.getHeight(), Config.ARGB_8888);
// 得到畫布
Canvas canvas = new Canvas(output);
// 將畫布的四角圓化
final int color = Color.RED;
final Paint paint = new Paint();
// 得到與圖像相同大小的區域 由構造的四個值決定區域的位置以及大小
final Rect rect = new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight());
final RectF rectF = new RectF(rect);
// 值越大角度越明顯
final float roundPx = 30;
paint.setAntiAlias(true);
canvas.drawARGB(0, 0, 0, 0);
paint.setColor(color);
// drawRoundRect的第2,3個參數一樣則畫的是正圓的一角,如果數值不同則是橢圓的一角
canvas.drawRoundRect(rectF, roundPx, roundPx, paint);
paint.setXfermode(new PorterDuffXfermode(Mode.SRC_IN));
canvas.drawBitmap(bitmap, rect, rect, paint);
return output;
}

最重要的一點圖片一定是png格式的。


沒大家說的那麼麻煩,已經有許多實現的類庫,沒必要自己造輪子了。

比如FaceBook出品的Fresco(中文文檔: Fresco | 引入Fresco )

第一步:引入支持

dependencies {
compile "com.facebook.fresco:fresco:0.9.0+"
}

第二步:使用SimpleDraweeView代替ImageView

&
&&>

&

&

注意其中的:

app:roundedCornerRadius="2dp"

這樣你就得到了一個2dp圓角的ImageView。

除了圓角之外,Fresco還支持圓形、佔位符、載入失敗時的占點陣圖、點擊重新載入、顯示一個進度條、背景、疊加圖、按壓狀態下的疊加圖、漸進式……(太多了,基本上只要你能想到的,它都…)。

除此功能豐富之外,關鍵是性能還超牛逼,我最初開始使用Fresco的原因就是為了解決圖片太多造成的界面卡頓~

恁這還等啥嘞!趕緊用起來啊!


更正:動畫沒問題,但有鋸齒,最高票數的那兩人都是有鋸齒的,並且不是加一兩個網上搜來的參數就能解決。

沒法高效,回答裡面用bitmapShader的,如果

這個view只是想下邊圓角,上半部分不變,並且要做個縮小動畫的話,目前來說,是無法實現的。

然後用clipPath是可行的,但有鋸齒,並且不支持硬體加速,也就是說做動畫會有問題。

用path自己可以畫原角,但效率低,如果要做動畫會卡,但用來做普通展示的話還行。


自定義個view,很簡單,或者網上搜,多的很,圓角ImageView


直接使用v4包里的


前面說寫個shape 你不是一個人→_→~


寫個shape不就行了嗎


別用cardview別用cardview別用cardview

cardview在5.0以下的兼容做法是設置一個padding保證圓角不被覆蓋,想像一下效果


CardView只是容器,並不負責什麼圖片裁剪,如果對少量圖片進行圓角裁剪,可以考慮直接利用canvas和BitmapShader繪製一個圓角矩形就可以了。

如果圖片很多,為了避免大量Bitmap的創建和回收,也為了避免觸發GC,可以考慮用Bitmap池和LRU演算法對圖片處理中要用的Bitmap進行統一管理,這個可以去Github上看一下Glide的LRUBitmapPool的實現。


採用clipPath會有鋸齒而且沒有辦法解決,最後直接用support v4庫的RoundedBitmapDrawable,重寫ImageView的setImageBitmap,根據傳入的Bitmap創建RoundedBitmapDrawable再調用setImageDrawable。


但是 很多的圓角矩形都有問題, 就是-------------------鋸齒,圖片小了 還看不出來 一旦大圖 圓角弧度越大 鋸齒毛邊越明顯 ,硬體加速開啟,各個手機也不一樣 ,請問這個怎麼解決. 我在想,可不可以讓美工切一個內透明圓角的圖片覆蓋上去? 這樣豈不是很easy,但是又不想讓美工覺得我自己實現不了,這樣我很沒面子啊,所以 ----------------我該怎麼辦?


1.canvas根據一個繪製圓形的Path去剪裁自己(效率比較低)

2.使用BitmapShader(Glide是使用這個實現的)

3.使用Xfermode實現


寫個style不就行了嗎

搞笑點重寫個view


簡單,高效

-------------------------------

什麼是簡單+高效?


喊美工過來


推薦閱讀:

如何做一個有高性能混合開發iOS/Android應用?
BiliBili客戶端中瀑布流的圖片是怎麼做到寬度固定,根據圖片比例來設置長度呢?
Android應用開發大神用過這個網站嗎?該怎樣學習和使用?
Android 開發中有什麼經典的輪子值得自己去實現一遍?
做用戶界面設計,1920*1080 解析度智能電視的 SafeZone 應該是多大?

TAG:Android應用 | Android開發 | Android |