Android編程實(shí)現(xiàn)自定義ImageView圓圖功能的方法
本文實(shí)例講述了Android編程實(shí)現(xiàn)自定義ImageView圓圖功能的方法。分享給大家供大家參考,具體如下:
首先很感謝開(kāi)源項(xiàng)目Universal Image Loader圖片加載框架。之前也看過(guò)一段時(shí)間框架源碼,但是卻沒(méi)有時(shí)間進(jìn)行知識(shí)點(diǎn)的總結(jié)。
今天項(xiàng)目遇到了需要實(shí)現(xiàn)圓頭像的編輯顯示,Universal就已經(jīng)提供了這個(gè)顯示RoundedBitmapDisplayer這個(gè)類(lèi)實(shí)現(xiàn)了圓圖功能??此拇a可以發(fā)現(xiàn)是實(shí)現(xiàn)的Drawable
public static class RoundedDrawable extends Drawable {
protected final float cornerRadius;
protected final int margin;
protected final RectF mRect = new RectF(),
mBitmapRect;
protected final BitmapShader bitmapShader;
protected final Paint paint;
public RoundedDrawable(Bitmap bitmap, int cornerRadius, int margin) {
this.cornerRadius = cornerRadius;
this.margin = margin;
bitmapShader = new BitmapShader(bitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
mBitmapRect = new RectF (margin, margin, bitmap.getWidth() - margin, bitmap.getHeight() - margin);
paint = new Paint();
paint.setAntiAlias(true);
paint.setShader(bitmapShader);
}
@Override
protected void onBoundsChange(Rect bounds) {
super.onBoundsChange(bounds);
mRect.set(margin, margin, bounds.width() - margin, bounds.height() - margin);
// Resize the original bitmap to fit the new bound
Matrix shaderMatrix = new Matrix();
shaderMatrix.setRectToRect(mBitmapRect, mRect, Matrix.ScaleToFit.FILL);
bitmapShader.setLocalMatrix(shaderMatrix);
}
@Override
public void draw(Canvas canvas) {
canvas.drawRoundRect(mRect, cornerRadius, cornerRadius, paint);
}
@Override
public int getOpacity() {
return PixelFormat.TRANSLUCENT;
}
@Override
public void setAlpha(int alpha) {
paint.setAlpha(alpha);
}
@Override
public void setColorFilter(ColorFilter cf) {
paint.setColorFilter(cf);
}
}
其實(shí)總結(jié)下來(lái),上面圓圖實(shí)現(xiàn)步驟就是:
1、通過(guò)bitmap初始化位圖著色器BitmapShader類(lèi)
2、計(jì)算bitmap原始圖片的rect
3、計(jì)算放置圖片需要的rect
4、使用Matrix類(lèi)對(duì)兩個(gè)rect進(jìn)行壓縮,然后復(fù)制給BitmapShader著色器里去。最后是畫(huà)布畫(huà)圖。
(剛開(kāi)始一直以為shader是陰影的意思,原來(lái)有道一下是著色器的意思,這個(gè)翻譯其實(shí)對(duì)我理解代碼還是很重要的,所以不要想當(dāng)然,要勤奮點(diǎn),這個(gè)是優(yōu)秀程序員必備要素。)
最后我要實(shí)現(xiàn)的是繼承ImageView實(shí)現(xiàn)圓圖
public class URoundedImageView extends ImageView {
private Paint mBitmapPaint,mBackgroundPaint;
private BitmapShader mBitmapShader;
private RectF mBitmapRect , mRect;
private int borderWidth;
private Bitmap mBitmap;
private Matrix shaderMatrix;
public URoundedImageView(Context context, AttributeSet attrs,
int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
public URoundedImageView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public URoundedImageView(Context context) {
super(context);
init();
}
private void init(){
mBitmapPaint = new Paint();
mBitmapPaint.setAntiAlias(true);
mBackgroundPaint = new Paint();
mBackgroundPaint.setAntiAlias(true);
mBackgroundPaint.setColor(Color.WHITE);
borderWidth = 5;
mRect = new RectF();
shaderMatrix = new Matrix();
}
@Override
protected void onLayout(boolean changed, int left, int top, int right,
int bottom) {
// TODO Auto-generated method stub
super.onLayout(changed, left, top, right, bottom);
}
@Override
protected void onDraw(Canvas canvas) {
mBitmap = ((BitmapDrawable) getDrawable()).getBitmap();
if (getWidth() == 0 || getHeight() == 0 || mBitmap == null) {
return;
}
int w = getWidth();
int h = getHeight();
int radius = Math.min(w, h) / 2;
canvas.drawCircle(w / 2, h / 2, radius, mBackgroundPaint);
//傳入bitmap初始化位圖著色器
if (mBitmapShader == null) {
mBitmapShader = new BitmapShader(mBitmap, Shader.TileMode.CLAMP,
Shader.TileMode.CLAMP);
}
if (mBitmapRect == null) {
mBitmapRect = new RectF(borderWidth, borderWidth,
mBitmap.getWidth() - borderWidth, mBitmap.getHeight()
- borderWidth);
}
mBitmapPaint.setShader(mBitmapShader);
mRect.set(borderWidth, borderWidth, w - borderWidth, h - borderWidth);
//對(duì)bitmap原始圖進(jìn)行縮放
shaderMatrix.setRectToRect(mBitmapRect, mRect, Matrix.ScaleToFit.FILL);
mBitmapShader.setLocalMatrix(shaderMatrix);
canvas.drawRoundRect(mRect, radius, radius, mBitmapPaint);
}
}
剛開(kāi)始寫(xiě)的不夠規(guī)范,直接在ondraw方法里面new一些需要的對(duì)象,lint提醒我們Avoid object allocations during draw/layout operations (preallocate and reuse instead)這個(gè)warning。因?yàn)閛ndraw會(huì)不斷調(diào)用,如果一直new對(duì)象的話會(huì)吃內(nèi)存。所以為了避免重復(fù)new對(duì)象,根據(jù)自己的需求進(jìn)行判空操作。具體根據(jù)自己需求來(lái)優(yōu)化代碼,有時(shí)候?yàn)榱诉_(dá)到需求也沒(méi)辦法做到在ondraw方法里不出現(xiàn)重復(fù)new對(duì)象的現(xiàn)象。
總結(jié):多參考優(yōu)秀的開(kāi)源項(xiàng)目,用正確的方法做正確的事情!
更多關(guān)于Android相關(guān)內(nèi)容感興趣的讀者可查看本站專(zhuān)題:《Android圖形與圖像處理技巧總結(jié)》、《Android開(kāi)發(fā)入門(mén)與進(jìn)階教程》、《Android調(diào)試技巧與常見(jiàn)問(wèn)題解決方法匯總》、《Android基本組件用法總結(jié)》、《Android視圖View技巧總結(jié)》、《Android布局layout技巧總結(jié)》及《Android控件用法總結(jié)》
希望本文所述對(duì)大家Android程序設(shè)計(jì)有所幫助。
- Android自定義ImageView實(shí)現(xiàn)自動(dòng)放大縮小動(dòng)畫(huà)
- Android自定義圓角ImageView控件
- Android 自定義imageview實(shí)現(xiàn)圖片縮放實(shí)例詳解
- Android自定義控件之圓形、圓角ImageView
- Android自定義GestureDetector實(shí)現(xiàn)手勢(shì)ImageView
- android自定義ImageView仿圖片上傳示例
- Android自定義ImageView實(shí)現(xiàn)在圖片上添加圖層效果
- Android通過(guò)自定義ImageView控件實(shí)現(xiàn)圖片的縮放和拖動(dòng)的實(shí)現(xiàn)代碼
- Android 自定義圓形頭像CircleImageView支持加載網(wǎng)絡(luò)圖片的實(shí)現(xiàn)代碼
- Android自定義圓角ImageView
- Android布局自定義Shap圓形ImageView可以單獨(dú)設(shè)置背景與圖片
相關(guān)文章
安裝android開(kāi)發(fā)環(huán)境原始版(windows版)
安裝android開(kāi)發(fā)環(huán)境原始版(windows版)的詳細(xì)步驟2013-03-03
Android使用開(kāi)源組件PagerBottomTabStrip實(shí)現(xiàn)底部菜單和頂部導(dǎo)航功能
這篇文章主要介紹了Android使用PagerBottomTabStrip實(shí)現(xiàn)底部菜單和頂部導(dǎo)航功能,本文給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2018-08-08
取消Android Studio項(xiàng)目與SVN關(guān)聯(lián)的方法
今天小編就為大家分享一篇關(guān)于取消Android Studio項(xiàng)目與SVN關(guān)聯(lián)的方法,小編覺(jué)得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來(lái)看看吧2018-12-12
詳解關(guān)于Android Studio中安裝和gradle的一些坑
本篇文章主要介紹了關(guān)于Android Studio中安裝和gradle的一些坑,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-10-10
Android編程設(shè)計(jì)模式之訪問(wèn)者模式詳解
這篇文章主要介紹了Android編程設(shè)計(jì)模式之訪問(wèn)者模式,詳細(xì)分析了訪問(wèn)者模式的概念、功能、原理、使用場(chǎng)景并結(jié)合實(shí)例形式給出了Android訪問(wèn)者模式的具體實(shí)現(xiàn)技巧與相關(guān)操作注意事項(xiàng),需要的朋友可以參考下2017-12-12
Android基于widget組件實(shí)現(xiàn)物體移動(dòng)/控件拖動(dòng)功能示例
這篇文章主要介紹了Android基于widget組件實(shí)現(xiàn)物體移動(dòng)/控件拖動(dòng)功能,結(jié)合實(shí)例形式分析了widget組件在桌面應(yīng)用中的事件響應(yīng)與屬性動(dòng)態(tài)操作相關(guān)實(shí)現(xiàn)技巧,需要的朋友可以參考下2016-10-10
Android實(shí)現(xiàn)拍照、選擇圖片并裁剪圖片功能
這篇文章主要為大家詳細(xì)介紹了Android實(shí)現(xiàn)拍照、選擇圖片并裁剪圖片功能的相關(guān)資料,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2016-05-05
Kotlin圖文并茂講解續(xù)體與續(xù)體攔截器和調(diào)度器
這篇文章主要介紹了Kotlin開(kāi)發(fā)中續(xù)體與續(xù)體攔截器和調(diào)度器的相關(guān)使用,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2022-08-08
Android組件Glide實(shí)現(xiàn)圖片平滑滾動(dòng)效果
這篇文章主要介紹了Android組件Glide實(shí)現(xiàn)圖片平滑滾動(dòng)效果的相關(guān)資料,具有一定的參考價(jià)值,需要的朋友可以參考下2016-07-07

