android自定義view-打造圓形ImageView(四)終結篇
阿新 • • 發佈:2019-01-29
上面公佈了兩個對外方法,如果用的時候覺得醜,就重新設定一下數值就會看到意想不到的效果:package com.beyole.view; import java.lang.ref.WeakReference; import android.content.Context; import android.graphics.Bitmap; import android.graphics.Bitmap.Config; import android.graphics.Canvas; import android.graphics.Paint; import android.graphics.PorterDuff.Mode; import android.graphics.PorterDuffXfermode; import android.graphics.RadialGradient; import android.graphics.Shader; import android.graphics.Xfermode; import android.graphics.drawable.Drawable; import android.util.AttributeSet; import android.widget.ImageView; public class GradientImageView extends ImageView { // 白色邊緣大小 private int mGradientBorder = 7; // 設定白色邊緣與漸變間距 private int mGradientGap = 5; // 畫筆 private Paint mPaint; // 使用快取機制來儲存處理好的bitmap,便於GC private WeakReference<Bitmap> mWeakBitmap; // 設定Xfermode的模式為DST_IN private Xfermode xfermode = new PorterDuffXfermode(Mode.DST_IN); // 蒙板圖層 private Bitmap mMaskBitmap; public GradientImageView(Context context) { this(context, null); } public GradientImageView(Context context, AttributeSet attrs) { this(context, attrs, 0); } public GradientImageView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); // 初始化畫筆 mPaint = new Paint(); mPaint.setAntiAlias(true); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); // 強制寬高一致,以最小的值為準 int mWidth = Math.min(getMeasuredWidth(), getMeasuredHeight()); setMeasuredDimension(mWidth, mWidth); } @Override protected void onDraw(Canvas canvas) { // 從快取中取出圖片 Bitmap bitmap = mWeakBitmap == null ? null : mWeakBitmap.get(); // 如果沒有快取或者被回收了,則重新繪製 if (bitmap == null || bitmap.isRecycled()) { // 獲取背景drawable Drawable drawable = getDrawable(); // 如果有背景圖則繪製 if (drawable != null) { // 拿到drawable的長度和寬度 int dWidth = drawable.getIntrinsicWidth(); int dHeight = drawable.getIntrinsicHeight(); bitmap = Bitmap.createBitmap(getWidth(), getHeight(), Config.ARGB_8888); // 建立畫布 Canvas canvas1 = new Canvas(bitmap); // 設定圖片縮放比率 float scale = 1.0f; scale = Math.max(getWidth() * 1.0f / dWidth, getHeight() * 1.0f / dHeight); // 縮放圖片 drawable.setBounds(0, 0, (int) (scale * dWidth), (int) (scale * dHeight)); // 繪製DST圖片 drawable.draw(canvas1); // 繪製SRC圖片 if (mMaskBitmap == null || mMaskBitmap.isRecycled()) { mMaskBitmap = drawType(); } // 重置畫筆 mPaint.reset(); // 不採用濾波 mPaint.setFilterBitmap(false); mPaint.setXfermode(xfermode); canvas1.drawBitmap(mMaskBitmap, 0, 0, mPaint); Paint paint1 = new Paint(Paint.ANTI_ALIAS_FLAG); paint1.setColor(0xffffffff); paint1.setStrokeWidth(mGradientBorder); paint1.setStyle(Paint.Style.STROKE); paint1.setXfermode(new PorterDuffXfermode(Mode.SRC_IN)); canvas1.drawCircle(getWidth() / 2, getHeight() / 2, getWidth() / 2 - mGradientGap, paint1); // drawable.draw(canvas); // 繪製處理好的圖形 mPaint.setXfermode(null); canvas.drawBitmap(bitmap, 0, 0, mPaint); // 快取圖片 mWeakBitmap = new WeakReference<Bitmap>(bitmap); } } if (bitmap != null) { mPaint.setXfermode(null); canvas.drawBitmap(bitmap, 0.0f, 0.0f, mPaint); } } /** * 繪製形狀,作為src * * @return */ private Bitmap drawType() { Bitmap bitmap = Bitmap.createBitmap(getWidth(), getHeight(), Bitmap.Config.ARGB_8888); Canvas canvas = new Canvas(bitmap); // 建立畫筆 Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG); paint.setDither(true); RadialGradient gradient = new RadialGradient(getWidth() / 2, getHeight() / 2, getWidth() / 2, new int[] { 0xff5d5d5d, 0xff5d5d5d, 0x00ffffff }, new float[] { 0.f, 0.9f, 1.0f }, Shader.TileMode.CLAMP); paint.setShader(gradient); canvas.drawCircle(getWidth() / 2, getWidth() / 2, getWidth() / 2, paint); return bitmap; } // 在重繪中進行mask和dst的記憶體回收 @Override public void invalidate() { mWeakBitmap = null; if (mMaskBitmap != null) { mMaskBitmap.recycle(); mMaskBitmap = null; } super.invalidate(); } // 對外公佈白色邊緣寬度 public void setGradientBorder(int gradientBorder) { this.mGradientBorder = gradientBorder; } // 對外公佈白色邊緣與漸變間距 public void setGradientGap(int gradientGap) { this.mGradientGap = gradientGap; } }