Android神话级圆形图片控件RoundImageView

原文地址:https://blog.****.net/u011192530/article/details/53836546

 

RoundImageView是在不修改ImageView原有绘图逻辑的情况下实现的圆形特性,完全兼容ImageView的所有特性。
无论你的图像控件布局是什么样的,图像内容是什么样的,RoundImageView不圆不是英雄!
无论你的图像控件ScaleType是什么样的,矩阵转换MATRIX是什么样的,RoundImageView不圆不是传说!
无论你的控件或图像经过何种变换,比如内边距偏移,缩放,居中等等,你会发现一个圆紧紧的跟随着你的控件或图片,不离不弃,这就是神话级的圆形控件RoundImageView!

RoundImageView的使用非常简单,无需任何额外依赖和xml属性配置,让哪些动辄就弄几个xml属性的都消失!
以下是几个常用属性设置接口:
1、setRoundMode:设置圆形模式。RoundImageView支持两种圆形模式:
(1)圆形视图:ROUND_VIEW, 使视图组件变圆;
(2)圆形图片:ROUND_DRAWABLE,使图片内容变圆。
2、setBorderColor:设置圆环颜色,默认为透明色;
3、setBorderWidth:设置圆环宽度,默认为0。如果圆环宽度小于等于0,圆环不会被绘制;
4、setFillColor:设置圆形区域填充背景色,默认为透明色。

源代码如下:

package com.example.roundimageview;
 
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Paint.Style;
import android.graphics.PorterDuffXfermode;
import android.graphics.Rect;
import android.graphics.PorterDuff.Mode;
import android.os.Build;
import android.util.AttributeSet;
import android.widget.ImageView;
 
public class RoundImageView extends ImageView {
 
	public enum RoundMode {
		ROUND_VIEW, ROUND_DRAWABLE
	}
 
	private static final int DEFAULT_BORDER_WIDTH = 0;
	private static final int DEFAULT_BORDER_COLOR = Color.TRANSPARENT;
	private static final int DEFAULT_FILL_COLOR = Color.TRANSPARENT;
 
	private boolean roundDisable;
	private RoundMode roundMode = RoundMode.ROUND_DRAWABLE;
	private int borderColor = DEFAULT_BORDER_COLOR;
	private int borderWidth = DEFAULT_BORDER_WIDTH;
	private int fillColor = DEFAULT_FILL_COLOR;
 
	private Paint borderPaint;
	private Paint fillPaint;
	private Paint imagePaint;
	private Paint portPaint;
 
	private Rect bounds = new Rect();
	private float radius = 0;
	private float cx = 0;
	private float cy = 0;
 
	public RoundImageView(Context context) {
		super(context);
		initView();
	}
 
	public RoundImageView(Context context, AttributeSet attrs) {
		super(context, attrs);
		initView();
	}
 
	public RoundImageView(Context context, AttributeSet attrs, int defStyleAttr) {
		super(context, attrs, defStyleAttr);
		initView();
	}
 
	private void initView() {
		portPaint = new Paint();
		portPaint.setAntiAlias(true);
 
		borderPaint = new Paint();
		borderPaint.setAntiAlias(true);
		borderPaint.setColor(DEFAULT_BORDER_COLOR);
		borderPaint.setStrokeWidth(DEFAULT_BORDER_WIDTH);
		borderPaint.setStyle(Style.STROKE);
 
		fillPaint = new Paint();
		fillPaint.setAntiAlias(true);
		fillPaint.setColor(DEFAULT_FILL_COLOR);
		fillPaint.setStyle(Style.FILL);
 
		imagePaint = new Paint();
		imagePaint.setAntiAlias(true);
		imagePaint.setXfermode(new PorterDuffXfermode(Mode.SRC_IN));
	}
 
	public void setRoundMode(RoundMode roundMode) {
		if (roundMode == null) {
			throw new IllegalArgumentException("roundMode is null.");
		}
 
		if (this.roundMode != roundMode) {
			this.roundMode = roundMode;
			invalidate();
		}
	}
 
	public void setRoundDisable(boolean roundDisable) {
		if (this.roundDisable != roundDisable) {
			this.roundDisable = roundDisable;
			invalidate();
		}
	}
 
	public boolean isRoundDisable() {
		return roundDisable;
	}
 
	public void setBorderColor(int borderColor) {
		if (this.borderColor != borderColor) {
			this.borderColor = borderColor;
			borderPaint.setColor(borderColor);
			invalidate();
		}
	}
 
	public void setBorderWidth(int borderWidth) {
		if (this.borderWidth != borderWidth) {
			this.borderWidth = borderWidth;
			borderPaint.setStrokeWidth(borderWidth);
			invalidate();
		}
	}
 
	public void setFillColor(int fillColor) {
		if (this.fillColor != fillColor) {
			this.fillColor = fillColor;
			fillPaint.setColor(fillColor);
			invalidate();
		}
	}
 
	@Override
	protected void onDraw(Canvas canvas) {
 
		if (roundDisable) {
			super.onDraw(canvas);
			return;
		}
 
		if (getDrawable() == null && roundMode == RoundMode.ROUND_DRAWABLE) {
			super.onDraw(canvas);
			return;
		}
 
		computeRoundBounds();
		drawCircle(canvas);
		drawImage(canvas);
 
	}
 
	private void drawImage(Canvas canvas) {
		Bitmap src = Bitmap.createBitmap(getWidth(), getHeight(), Bitmap.Config.ARGB_4444);
		super.onDraw(new Canvas(src));
 
		Bitmap port = Bitmap.createBitmap(getWidth(), getHeight(), Bitmap.Config.ARGB_4444);
		Canvas portCanvas = new Canvas(port);
 
		int saveCount = portCanvas.getSaveCount();
		portCanvas.save();
		adjustCanvas(portCanvas);
		portCanvas.drawCircle(cx, cy, radius, portPaint);
		portCanvas.restoreToCount(saveCount);
 
		portCanvas.drawBitmap(src, 0, 0, imagePaint);
		src.recycle();
 
		canvas.drawBitmap(port, 0, 0, null);
		port.recycle();
 
	}
 
	private void drawCircle(Canvas canvas) {
		int saveCount = canvas.getSaveCount();
		canvas.save();
 
		adjustCanvas(canvas);
 
		canvas.drawCircle(cx, cy, radius, fillPaint);
		if (borderWidth > 0) {
			canvas.drawCircle(cx, cy, radius - borderWidth / 2f, borderPaint);
		}
 
		canvas.restoreToCount(saveCount);
 
	}
 
	private void computeRoundBounds() {
		if (roundMode == RoundMode.ROUND_VIEW) {
			bounds.left = getPaddingLeft();
			bounds.top = getPaddingTop();
			bounds.right = getWidth() - getPaddingRight();
			bounds.bottom = getHeight() - getPaddingBottom();
		} else if (roundMode == RoundMode.ROUND_DRAWABLE) {
			getDrawable().copyBounds(bounds);
		} else {
			throw new RuntimeException("unknown round mode:" + roundMode);
		}
 
		radius = Math.min(bounds.width(), bounds.height()) / 2f;
		cx = bounds.left + bounds.width() / 2f;
		cy = bounds.top + bounds.height() / 2f;
	}
 
	private void adjustCanvas(Canvas canvas) {
		if (roundMode == RoundMode.ROUND_DRAWABLE) {
			if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
				if (getCropToPadding()) {
					final int scrollX = getScrollX();
					final int scrollY = getScrollY();
					canvas.clipRect(scrollX + getPaddingLeft(), scrollY + getPaddingTop(),
							scrollX + getRight() - getLeft() - getPaddingRight(),
							scrollY + getBottom() - getTop() - getPaddingBottom());
				}
			}
 
			canvas.translate(getPaddingLeft(), getPaddingTop());
			if (getImageMatrix() != null) {
				Matrix m = new Matrix(getImageMatrix());
				canvas.concat(m);
			}
		}
	}
 
}

 

1、默认使用

RoundImageView imageView=new RoundImageView(getApplicationContext());
		imageView.setImageResource(R.drawable.m);
		setContentView(imageView,new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));

Android神话级圆形图片控件RoundImageView

 

 2、给组件加点偏移

RoundImageView imageView=new RoundImageView(getApplicationContext());
		
		imageView.setPadding(200, 100, 20, 0);
		
		imageView.setImageResource(R.drawable.m);
		setContentView(imageView,new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));


Android神话级圆形图片控件RoundImageView