1. 程式人生 > >android自定義view-打造圓形ImageView(二)

android自定義view-打造圓形ImageView(二)

package com.beyole.view;

import java.lang.ref.WeakReference;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.PorterDuff.Mode;
import android.graphics.PorterDuffXfermode;
import android.graphics.RectF;
import android.graphics.Xfermode;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.util.Log;
import android.util.TypedValue;
import android.widget.ImageView;

import com.beyole.roundimageview.R;

public class XfermodeRoundImageView extends ImageView {

	// ImageView型別
	private int type;
	// 圓形圖片
	private static final int TYPE_CIRCLE = 0;
	// 圓角圖片
	private static final int TYPE_ROUND = 1;
	// 預設圓角寬度
	private static final int BORDER_RADIUS_DEFAULT = 10;
	// 獲取圓角寬度
	private int mBorderRadius;
	// 畫筆
	private Paint mPaint;
	// 使用快取機制來儲存處理好的bitmap,便於GC
	private WeakReference<Bitmap> mWeakBitmap;
	// 設定Xfermode的模式為DST_IN
	private Xfermode xfermode = new PorterDuffXfermode(Mode.DST_IN);
	// 蒙板圖層
	private Bitmap mMaskBitmap;

	public XfermodeRoundImageView(Context context) {
		this(context, null);
	}

	public XfermodeRoundImageView(Context context, AttributeSet attrs) {
		this(context, attrs, 0);
	}

	public XfermodeRoundImageView(Context context, AttributeSet attrs, int defStyle) {
		super(context, attrs, defStyle);
		// 初始化畫筆
		mPaint = new Paint();
		mPaint.setAntiAlias(true);
		// 獲取自定義屬性值
		TypedArray array = context.getTheme().obtainStyledAttributes(attrs, R.styleable.XfermodeRoundImageView, defStyle, 0);
		int count = array.getIndexCount();
		for (int i = 0; i < count; i++) {
			int attr = array.getIndex(i);
			switch (attr) {
			case R.styleable.XfermodeRoundImageView_borderRadius:
				// 獲取圓角大小
				mBorderRadius = array.getDimensionPixelSize(R.styleable.XfermodeRoundImageView_borderRadius, (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, BORDER_RADIUS_DEFAULT, getResources().getDisplayMetrics()));
				break;
			case R.styleable.XfermodeRoundImageView_imageType:
				// 獲取ImageView的型別
				type = array.getInt(R.styleable.XfermodeRoundImageView_imageType, TYPE_CIRCLE);
				break;
			}
		}
		// Give back a previously retrieved StyledAttributes, for later re-use.
		array.recycle();
	}

	@Override
	protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
		super.onMeasure(widthMeasureSpec, heightMeasureSpec);
		// 如果是圓形,則強制寬高一致,以最小的值為準
		if (type == TYPE_CIRCLE) {
			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;
				if (type == TYPE_CIRCLE) {
					scale = Math.max(getWidth() * 1.0f / dWidth, getHeight() * 1.0f / dHeight);
				} else {
					scale = getWidth() * 1.0F / Math.min(dWidth, 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);
				// 繪製處理好的圖形
				mPaint.setXfermode(null);
				canvas.drawBitmap(bitmap, 0, 0, mPaint);
				// drawable.draw(canvas);
				// 快取圖片
				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.setColor(Color.BLACK);
		// 如果type為圓形
		if (type == TYPE_CIRCLE) {
			canvas.drawCircle(getWidth() / 2, getWidth() / 2, getWidth() / 2, paint);
		} else {
			canvas.drawRoundRect(new RectF(0, 0, getWidth(), getHeight()), mBorderRadius, mBorderRadius, paint);
		}
		return bitmap;
	}

	// 在重繪中進行mask和dst的記憶體回收
	@Override
	public void invalidate() {
		mWeakBitmap = null;
		if (mMaskBitmap != null) {
			mMaskBitmap.recycle();
			mMaskBitmap = null;
		}
		super.invalidate();
	}

}
activity_main.xml: