Android編程實(shí)現(xiàn)自定義ImageView圓圖功能的方法
本文實(shí)例講述了Android編程實(shí)現(xiàn)自定義ImageView圓圖功能的方法。分享給大家供大家參考,具體如下:
首先很感謝開源項(xiàng)目Universal Image Loader圖片加載框架。之前也看過一段時(shí)間框架源碼,但是卻沒有時(shí)間進(jìn)行知識(shí)點(diǎn)的總結(jié)。
今天項(xiàng)目遇到了需要實(shí)現(xiàn)圓頭像的編輯顯示,Universal就已經(jīng)提供了這個(gè)顯示RoundedBitmapDisplayer這個(gè)類實(shí)現(xiàn)了圓圖功能。看它的代碼可以發(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é)下來,上面圓圖實(shí)現(xiàn)步驟就是:
1、通過bitmap初始化位圖著色器BitmapShader類
2、計(jì)算bitmap原始圖片的rect
3、計(jì)算放置圖片需要的rect
4、使用Matrix類對(duì)兩個(gè)rect進(jìn)行壓縮,然后復(fù)制給BitmapShader著色器里去。最后是畫布畫圖。
(剛開始一直以為shader是陰影的意思,原來有道一下是著色器的意思,這個(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);
}
}
剛開始寫的不夠規(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ù)自己需求來優(yōu)化代碼,有時(shí)候?yàn)榱诉_(dá)到需求也沒辦法做到在ondraw方法里不出現(xiàn)重復(fù)new對(duì)象的現(xiàn)象。
總結(jié):多參考優(yōu)秀的開源項(xiàng)目,用正確的方法做正確的事情!
更多關(guān)于Android相關(guān)內(nèi)容感興趣的讀者可查看本站專題:《Android圖形與圖像處理技巧總結(jié)》、《Android開發(fā)入門與進(jìn)階教程》、《Android調(diào)試技巧與常見問題解決方法匯總》、《Android基本組件用法總結(jié)》、《Android視圖View技巧總結(jié)》、《Android布局layout技巧總結(jié)》及《Android控件用法總結(jié)》
希望本文所述對(duì)大家Android程序設(shè)計(jì)有所幫助。
- Android自定義ImageView實(shí)現(xiàn)自動(dòng)放大縮小動(dòng)畫
- 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通過自定義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?Springboot?實(shí)現(xiàn)SSE通信案例詳解
SSE是一種用于實(shí)現(xiàn)服務(wù)器主動(dòng)向客戶端推送數(shù)據(jù)的技術(shù),它基于?HTTP?協(xié)議,利用了其長連接特性,在客戶端與服務(wù)器之間建立一條持久化連接,并通過這條連接實(shí)現(xiàn)服務(wù)器向客戶端的實(shí)時(shí)數(shù)據(jù)推送,這篇文章主要介紹了Android?Springboot?實(shí)現(xiàn)SSE通信案例,需要的朋友可以參考下2024-07-07
Android使用selector修改TextView中字體顏色和背景色的方法
這篇文章主要介紹了Android使用selector修改TextView中字體顏色和背景色的方法,實(shí)例分析了selector方法的相關(guān)使用技巧,需要的朋友可以參考下2016-01-01
Android RecyclerView使用GridLayoutManager間距設(shè)置的方法
本篇文章主要介紹了Android RecyclerView使用GridLayoutManager間距設(shè)置的方法,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-12-12
Android ViewFlipper的詳解及實(shí)例
這篇文章主要介紹了Android ViewFlipper的詳解及實(shí)例的相關(guān)資料,通過本文希望能幫助大家理解這部分內(nèi)容,需要的朋友可以參考下2017-08-08
Android分頁中顯示出下面翻頁的導(dǎo)航欄的布局實(shí)例代碼
這篇文章主要介紹了Android分頁中顯示出下面翻頁的導(dǎo)航欄的布局實(shí)例代碼,需要的朋友可以參考下2017-04-04
深入學(xué)習(xí)Kotlin?枚舉的簡(jiǎn)潔又高效進(jìn)階用法
這篇文章主要為大家介紹了深入學(xué)習(xí)Kotlin?枚舉簡(jiǎn)潔又高效的進(jìn)階用法詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-05-05
Android基于方法池與回調(diào)實(shí)現(xiàn)登錄攔截的場(chǎng)景
這篇文章主要為大家介紹了Android基于方法池與回調(diào)實(shí)現(xiàn)登錄攔截的場(chǎng)景詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-08-08

