package com.mm.android.deviceaddmodule.mobilecommon.widget;
|
|
import android.content.Context;
|
import android.content.res.TypedArray;
|
import android.graphics.Bitmap;
|
import android.graphics.Canvas;
|
import android.graphics.Matrix;
|
import android.graphics.Paint;
|
import android.graphics.PorterDuff;
|
import android.graphics.PorterDuffXfermode;
|
import android.graphics.RectF;
|
import android.graphics.drawable.BitmapDrawable;
|
import android.graphics.drawable.ColorDrawable;
|
import android.graphics.drawable.Drawable;
|
import android.util.AttributeSet;
|
|
import com.mm.android.deviceaddmodule.R;
|
|
|
/**
|
* 自定义 ImageView 控件,实现了圆角和边框,以及按下变色
|
* 修改设置选中 颜色和 按下颜色 的方法 ,通过系统api调用, 移除java代码依赖, 只需要依赖xml和attr配置
|
*/
|
public class MLBorderImageView extends android.support.v7.widget.AppCompatImageView {
|
public static final int TYPE_SHAPE_CIRCLE = 1;
|
public static final int TYPE_SHAPE_RECT = 2;
|
// 图片的宽高
|
private int width;
|
private int height;
|
|
// 定义 Bitmap 的默认配置
|
private static final Bitmap.Config BITMAP_CONFIG = Bitmap.Config.RGB_565;
|
private static final int COLORDRAWABLE_DIMENSION = 1;
|
|
// 边框颜色
|
private int borderColor, borderSelectedColor,borderUnSelectedColor;
|
// 边框宽度
|
private int borderWidth;
|
|
// 圆角半径
|
private int radius;
|
// 图片类型(矩形,圆形)
|
private int shapeType;
|
|
|
public MLBorderImageView(Context context) {
|
super(context);
|
init(context, null);
|
}
|
|
public MLBorderImageView(Context context, AttributeSet attrs) {
|
super(context, attrs);
|
init(context, attrs);
|
}
|
|
public MLBorderImageView(Context context, AttributeSet attrs, int defStyleAttr) {
|
super(context, attrs, defStyleAttr);
|
init(context, attrs);
|
}
|
|
private void init(Context context, AttributeSet attrs) {
|
//初始化默认值
|
borderWidth = 0;
|
borderColor = 0xffffff;
|
|
radius = 16;
|
shapeType = 2;
|
|
// 获取控件的属性值
|
if (attrs != null) {
|
TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.MLBorderImageView);
|
borderColor = array.getColor(R.styleable.MLBorderImageView_border_color, borderColor);
|
borderUnSelectedColor = array.getColor(R.styleable.MLBorderImageView_border_color_normal, borderColor);
|
borderSelectedColor = array.getColor(R.styleable.MLBorderImageView_border_color_selected, borderColor);
|
borderWidth = array.getDimensionPixelOffset(R.styleable.MLBorderImageView_border_width, borderWidth);
|
|
radius = array.getDimensionPixelOffset(R.styleable.MLBorderImageView_radius, radius);
|
shapeType = array.getInteger(R.styleable.MLBorderImageView_shape_type, shapeType);
|
array.recycle();
|
}
|
|
setClickable(true);
|
setDrawingCacheEnabled(true);
|
setWillNotDraw(false);
|
}
|
|
|
@Override
|
protected void onDraw(Canvas canvas) {
|
|
if (shapeType == 0) {
|
super.onDraw(canvas);
|
return;
|
}
|
// 获取当前控件的 drawable
|
Drawable drawable = getDrawable();
|
if (drawable == null) {
|
return;
|
}
|
// 这里 get 回来的宽度和高度是当前控件相对应的宽度和高度(在 xml 设置)
|
if (getWidth() == 0 || getHeight() == 0) {
|
return;
|
}
|
// 获取 bitmap,即传入 imageView 的 bitmap
|
// Bitmap bitmap = ((BitmapDrawable) ((SquaringDrawable)
|
// drawable).getCurrent()).getBitmap();
|
// 获取 bitmap 方式,因为上边的获取会导致 Glide 加载的drawable 强转为 BitmapDrawable 出错
|
Bitmap bitmap = getBitmapFromDrawable(drawable);
|
drawDrawable(canvas, bitmap);
|
|
drawBorder(canvas);
|
}
|
|
/**
|
* 实现圆角的绘制
|
*
|
* @param canvas
|
* @param bitmap
|
*/
|
private void drawDrawable(Canvas canvas, Bitmap bitmap) {
|
// 画笔
|
Paint paint = new Paint();
|
// 颜色设置
|
paint.setColor(0xffffffff);
|
// 抗锯齿
|
paint.setAntiAlias(true);
|
//Paint 的 Xfermode,PorterDuff.Mode.SRC_IN 取两层图像的交集部分, 只显示上层图像。
|
PorterDuffXfermode xfermode = new PorterDuffXfermode(PorterDuff.Mode.CLEAR);
|
canvas.saveLayer(0, 0, width, height, null);
|
|
if (shapeType == 1) {
|
// 画遮罩,画出来就是一个和空间大小相匹配的圆(这里在半径上 -1 是为了不让图片超出边框)
|
canvas.drawCircle(width / 2, height / 2, width / 2 - 1, paint);
|
} else if (shapeType == 2) {
|
// 当ShapeType == 2 时 图片为圆角矩形 (这里在宽高上 -1 是为了不让图片超出边框)
|
RectF rectf = new RectF(1, 1, getWidth() - 1, getHeight() - 1);
|
canvas.drawRoundRect(rectf, radius + 1, radius + 1, paint);
|
}
|
|
paint.setXfermode(xfermode);
|
|
// 空间的大小 / bitmap 的大小 = bitmap 缩放的倍数
|
float scaleWidth = ((float) getWidth()) / bitmap.getWidth();
|
float scaleHeight = ((float) getHeight()) / bitmap.getHeight();
|
|
Matrix matrix = new Matrix();
|
matrix.postScale(scaleWidth, scaleHeight);
|
|
//bitmap 缩放
|
bitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);
|
|
//draw 上去
|
canvas.drawBitmap(bitmap, 0, 0, paint);
|
canvas.restore();
|
bitmap.recycle();
|
bitmap = null;
|
}
|
|
/**
|
* 绘制自定义控件边框
|
*
|
* @param canvas
|
*/
|
private void drawBorder(Canvas canvas) {
|
if (borderWidth > 0) {
|
Paint paint = new Paint();
|
paint.setStrokeWidth(borderWidth);
|
paint.setStyle(Paint.Style.STROKE);
|
paint.setColor(borderColor);
|
paint.setAntiAlias(true);
|
// 根据控件类型的属性去绘制圆形或者矩形
|
if (shapeType == 1) {
|
canvas.drawCircle(width / 2, height / 2, (width - borderWidth) / 2, paint);
|
} else if (shapeType == 2) {
|
// 当ShapeType = 1 时 图片为圆角矩形
|
RectF rectf = new RectF(borderWidth / 2, borderWidth / 2, getWidth() - borderWidth / 2,
|
getHeight() - borderWidth / 2);
|
canvas.drawRoundRect(rectf, radius, radius, paint);
|
}
|
}
|
}
|
|
/**
|
* 重写父类的 onSizeChanged 方法,检测控件宽高的变化
|
*
|
* @param w
|
* @param h
|
* @param oldw
|
* @param oldh
|
*/
|
@Override
|
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
|
super.onSizeChanged(w, h, oldw, oldh);
|
width = w;
|
height = h;
|
}
|
|
|
/**
|
* 这里是参考其他开发者获取Bitmap内容的方法, 之前是因为没有考虑到 Glide 加载的图片
|
* 导致drawable 类型是属于 SquaringDrawable 类型,导致强转失败
|
* 这里是通过drawable不同的类型来进行获取Bitmap
|
*
|
* @param drawable
|
* @return
|
*/
|
private Bitmap getBitmapFromDrawable(Drawable drawable) {
|
try {
|
Bitmap bitmap;
|
if (drawable instanceof BitmapDrawable) {
|
return ((BitmapDrawable) drawable).getBitmap();
|
} else if (drawable instanceof ColorDrawable) {
|
bitmap = Bitmap.createBitmap(COLORDRAWABLE_DIMENSION, COLORDRAWABLE_DIMENSION, BITMAP_CONFIG);
|
} else {
|
bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight(),
|
BITMAP_CONFIG);
|
}
|
Canvas canvas = new Canvas(bitmap);
|
drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
|
drawable.draw(canvas);
|
return bitmap;
|
} catch (OutOfMemoryError e) {
|
e.printStackTrace();
|
return null;
|
}
|
}
|
|
@Override
|
public void setSelected(boolean selected) {
|
super.setSelected(selected);
|
setBorderColor(selected);
|
}
|
|
@Override
|
public void setPressed(boolean pressed) {
|
super.setPressed(pressed);
|
if(isSelected()){
|
return;
|
}
|
setBorderColor(pressed);
|
}
|
|
private void setBorderColor(boolean selected) {
|
if(selected){
|
borderColor = borderSelectedColor;
|
}else{
|
borderColor = borderUnSelectedColor;
|
}
|
invalidate();
|
}
|
|
|
public void setRadius(int radius){
|
this.radius = radius;
|
invalidate();
|
}
|
|
public void setShapeType(int type){
|
this.shapeType = type;
|
}
|
|
|
}
|