Android 三種方式實現圓形ImageView
阿新 • • 發佈:2019-01-01
所有方式均繼承了ImageView
圓形圖片實現一:BitmapShader
package com.open.widget; import android.content.Context; import android.graphics.Bitmap; import android.graphics.BitmapShader; import android.graphics.Canvas; import android.graphics.Matrix; import android.graphics.Paint; import android.graphics.RectF; import android.graphics.Shader.TileMode; import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.Drawable; import android.util.AttributeSet; import android.widget.ImageView; /** * 1.BitmapShader * * @author Administrator * */ public class CircularImageView extends ImageView { private BitmapShader mBitmapShader; private Paint mBitmapPaint = new Paint(); private RectF mRoundRect=new RectF(); public CircularImageView(Context context) { super(context); initObjectAttribute(); } public CircularImageView(Context context, AttributeSet attrs) { this(context, attrs, 0); } public CircularImageView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); initObjectAttribute(); } @Override public void setImageResource(int resId) { super.setImageResource(resId); createBitmapShader(); } @Override public void setImageBitmap(Bitmap bm) { super.setImageBitmap(bm); // createBitmapShader(); } @Override public void setImageDrawable(Drawable drawable) { super.setImageDrawable(drawable); createBitmapShader(); } private void initObjectAttribute() { mBitmapPaint.setAntiAlias(true); // if(getScaleType() != ScaleType.CENTER_CROP) // { // setScaleType(ScaleType.CENTER_CROP); // } } private void createBitmapShader() { mBitmapShader = null; Drawable mDrawable = getDrawable(); if (mDrawable == null) { return; } if(mDrawable instanceof BitmapDrawable) { BitmapDrawable bd = (BitmapDrawable) mDrawable; Bitmap bitmap = bd.getBitmap(); mBitmapShader = new BitmapShader(bitmap, TileMode.CLAMP, TileMode.CLAMP); } else //if Drawable instanceof NinePathDrawable ,the code below is bad , because a view reference two bitmap ( one in NinePath , other is here) { int w = mDrawable.getIntrinsicWidth(); int h = mDrawable.getIntrinsicHeight(); Bitmap bitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888); Canvas canvas = new Canvas(bitmap); mDrawable.setBounds(0, 0, w, h); mDrawable.draw(canvas); mBitmapShader = new BitmapShader(bitmap, TileMode.CLAMP, TileMode.CLAMP); } } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); mRoundRect.set(0,0,getMeasuredWidth(),getMeasuredHeight()); } @Override protected void onDraw(Canvas canvas) { Drawable mDrawable = getDrawable(); if (null == mDrawable || null == mBitmapShader) { return; } Matrix mDrawMatrix= getImageMatrix(); if(null == mDrawMatrix) { mDrawMatrix =new Matrix(); } mBitmapShader.setLocalMatrix(mDrawMatrix); mBitmapPaint.setShader(mBitmapShader); canvas.drawCircle(getWidth()/2, getHeight()/2, Math.min(getWidth()/2, getHeight()/2), mBitmapPaint); } }
圓形圖片實現二:Path
package com.open.widget; import android.content.Context; import android.graphics.Canvas; import android.graphics.Matrix; import android.graphics.Paint; import android.graphics.PaintFlagsDrawFilter; import android.graphics.Path; import android.graphics.RectF; import android.graphics.Region; import android.graphics.drawable.Drawable; import android.util.AttributeSet; import android.widget.ImageView; /** * 2.Path * * @author Administrator * */ public class CircularImageView2 extends ImageView { private RectF mRoundRect=new RectF(); private Path mPath = new Path(); private PaintFlagsDrawFilter pfd=new PaintFlagsDrawFilter(0, Paint.ANTI_ALIAS_FLAG|Paint.FILTER_BITMAP_FLAG); public CircularImageView2(Context context) { super(context); initObjectAttribute(); } public CircularImageView2(Context context, AttributeSet attrs) { this(context, attrs, 0); } public CircularImageView2(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); initObjectAttribute(); } private void initObjectAttribute() { // if(getScaleType() != ScaleType.CENTER_CROP) // { // setScaleType(ScaleType.CENTER_CROP); // } } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); mRoundRect.set(0,0,getMeasuredWidth(),getMeasuredHeight()); } @Override protected void onDraw(Canvas canvas) { Drawable mDrawable = getDrawable(); if (mDrawable == null) { return; } if (mDrawable.getIntrinsicWidth() == 0 || mDrawable.getIntrinsicHeight() == 0) { return; // nothing to draw (empty bounds) } canvas.setDrawFilter(pfd); canvas.save(); mPath.reset(); canvas.clipPath(mPath); // makes the clip empty mPath.addCircle(getWidth()/2, getHeight()/2, Math.min(getWidth()/2, getHeight()/2), Path.Direction.CCW); canvas.clipPath(mPath, Region.Op.REPLACE); Matrix mDrawMatrix = getImageMatrix(); if (mDrawMatrix != null) { canvas.concat(mDrawMatrix); } mDrawable.draw(canvas); canvas.restore(); } }
圓形圖片實現三:setXfermode
package com.open.widget; import android.content.Context; import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.graphics.PorterDuff; import android.graphics.PorterDuffXfermode; import android.graphics.RectF; import android.graphics.Xfermode; import android.graphics.drawable.Drawable; import android.util.AttributeSet; import android.widget.ImageView; /** * 3.setXfermode * * @author Administrator * */ public class CircularImageView3 extends ImageView { private Paint paint = new Paint(); private Xfermode mXfermode = new PorterDuffXfermode(PorterDuff.Mode.DST_IN); private Bitmap maskBitmap=null; private RectF mRoundRect=new RectF(); private int oldWidth; private int oldHeight; public CircularImageView3(Context context) { super(context); initObjectAttribute(); } public CircularImageView3(Context context, AttributeSet attrs) { this(context, attrs, 0); } public CircularImageView3(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); initObjectAttribute(); } private void initObjectAttribute() { paint.setFlags(Paint.ANTI_ALIAS_FLAG); paint.setAntiAlias(true);// 設定畫筆的鋸齒效果。 true是去除,大家一看效果就明白了 // if(getScaleType() != ScaleType.CENTER_CROP) // { // setScaleType(ScaleType.CENTER_CROP); // } } private void create_mask_bitmap(int w , int h) { if(null != maskBitmap && !maskBitmap.isRecycled()) { maskBitmap.recycle(); maskBitmap=null; } maskBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888); Canvas mCanvas = new Canvas(maskBitmap); Paint mPaint = new Paint(Paint.ANTI_ALIAS_FLAG); mPaint.setColor(Color.TRANSPARENT); mCanvas.drawCircle(w/2, h/2, Math.min(w/2, h/2), paint); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); mRoundRect.set(0,0,getMeasuredWidth(),getMeasuredHeight()); if( oldWidth!=getMeasuredWidth() || oldHeight!=getMeasuredHeight() ) { oldWidth = getMeasuredWidth() ; oldHeight = getMeasuredHeight(); if(oldWidth > 0 && oldHeight >0) { create_mask_bitmap(oldWidth , oldHeight); } } } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); Drawable mDrawable = getDrawable(); if (mDrawable == null) { return; } if (mDrawable.getIntrinsicWidth() == 0 || mDrawable.getIntrinsicHeight() == 0) { return; // nothing to draw (empty bounds) } if(null == maskBitmap) { return; } int saveCount = canvas.getSaveCount(); canvas.save(); paint.setFilterBitmap(false); paint.setXfermode(mXfermode); canvas.drawBitmap(maskBitmap, null, mRoundRect, paint); paint.setXfermode(null); canvas.restoreToCount(saveCount); } }
這裡主要是重用了ImageView,如果你想強制繪製的View為圓角或者圓形圖片,把程式碼中註釋的程式碼開啟即可
private void initObjectAttribute()
{
mBitmapPaint.setAntiAlias(true);
// if(getScaleType() != ScaleType.CENTER_CROP)
// {
// setScaleType(ScaleType.CENTER_CROP);
// }
}
知識點不是很難,程式碼淺顯易懂,當然最好去熟讀一下ImageView的原始碼.
原始碼獲取地址: