效果如下:
全部代码:【ShapeImageView】
package xiaodan.www.amor_love.Utils;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.BitmapShader;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Paint.Style;
import android.graphics.Path;
import android.graphics.RectF;
import android.graphics.Shader;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.provider.MediaStore;
import android.util.AttributeSet;
import xiaodan.www.amor_love.R;
/**
* 可设置形状的ImageView,抗边缘锯齿
*
* @author 冯人唐
*/
public class ShapeImageView extends android.support.v7.widget.AppCompatImageView {
private static final Bitmap.Config BITMAP_CONFIG = Bitmap.Config.ARGB_8888;
private static final int COLORDRAWABLE_DIMENSION = 2;
//系统数据库存放图片的路径
private static final Uri STORAGE_URI = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
public static int SHAPE_REC = 1; // 矩形
public static int SHAPE_CIRCLE = 2; // 圆形
public static int SHAPE_OVAL = 3; // 椭圆
private final Matrix mShaderMatrix = new Matrix();
private float mBorderSize = 0; // 边框大小,默认为0,即无边框
private int mBorderColor = Color.WHITE; // 边框颜色,默认为白色
private int mShape = SHAPE_REC; // 形状,默认为直接矩形
private float mRoundRadius = 0; // 矩形的圆角半径,默认为0,即直角矩形
private float mRoundRadiusLeftTop, mRoundRadiusLeftBottom, mRoundRadiusRightTop, mRoundRadiusRightBottom;
private Paint mBorderPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
private RectF mViewRect = new RectF(); // imageview的矩形区域
private RectF mBorderRect = new RectF(); // 边框的矩形区域
private Paint mBitmapPaint = new Paint();
private BitmapShader mBitmapShader;
private Bitmap mBitmap;
private Path mPath = new Path();
public ShapeImageView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public ShapeImageView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle); // 虽然此处会调用setImageDrawable,但此时成员变量还未被正确初始化
init(attrs);
mBorderPaint.setStyle(Style.STROKE);
mBorderPaint.setStrokeWidth(mBorderSize);
mBorderPaint.setColor(mBorderColor);
mBorderPaint.setAntiAlias(true);
mBitmapPaint.setAntiAlias(true);
super.setScaleType(ScaleType.CENTER_CROP); // 固定为CENTER_CROP,其他不生效
}
private void init(AttributeSet attrs) {
TypedArray a = getContext().obtainStyledAttributes(attrs,
R.styleable.ShapeImageView);
mShape = a.getInt(R.styleable.ShapeImageView_siv_shape, mShape);
mRoundRadius = a.getDimension(R.styleable.ShapeImageView_siv_round_radius, mRoundRadius);
mBorderSize = a.getDimension(R.styleable.ShapeImageView_siv_border_size, mBorderSize);
mBorderColor = a.getColor(R.styleable.ShapeImageView_siv_border_color, mBorderColor);
mRoundRadiusLeftBottom = a.getDimension(R.styleable.ShapeImageView_siv_round_radius_leftBottom, mRoundRadius);
mRoundRadiusLeftTop = a.getDimension(R.styleable.ShapeImageView_siv_round_radius_leftTop, mRoundRadius);
mRoundRadiusRightBottom = a.getDimension(R.styleable.ShapeImageView_siv_round_radius_rightBottom, mRoundRadius);
mRoundRadiusRightTop = a.getDimension(R.styleable.ShapeImageView_siv_round_radius_rightTop, mRoundRadius);
a.recycle();
SelectorAttrs.obtainsAttrs(getContext(), this, attrs);
}
@Override
public void setImageResource(int resId) {
super.setImageResource(resId);
mBitmap = getBitmapFromDrawable(getDrawable());
setupBitmapShader();
}
public Bitmap getBitmapFromDrawable(Drawable drawable) {
if (drawable == null) {
return null;
}
if (drawable instanceof BitmapDrawable) {
return ((BitmapDrawable) drawable).getBitmap();
}
try {
Bitmap bitmap;
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 (Exception e) {
e.printStackTrace();
return null;
}
}
private void setupBitmapShader() {
// super(context, attrs, defStyle)调用setImageDrawable时,成员变量还未被正确初始化
if (mBitmapPaint == null) {
return;
}
if (mBitmap == null) {
invalidate();
return;
}
mBitmapShader = new BitmapShader(mBitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
mBitmapPaint.setShader(mBitmapShader);
// 固定为CENTER_CROP,使图片在view中居中并裁剪
mShaderMatrix.set(null);
// 缩放到高或宽 与view的高或宽 匹配
float scale = Math.max(getWidth() * 1f / mBitmap.getWidth(), getHeight() * 1f / mBitmap.getHeight());
// 由于BitmapShader默认是从画布的左上角开始绘制,所以把其平移到画布中间,即居中
float dx = (getWidth() - mBitmap.getWidth() * scale) / 2;
float dy = (getHeight() - mBitmap.getHeight() * scale) / 2;
mShaderMatrix.setScale(scale, scale);
mShaderMatrix.postTranslate(dx, dy);
mBitmapShader.setLocalMatrix(mShaderMatrix);
invalidate();
}
@Override
public void setImageDrawable(Drawable drawable) {
super.setImageDrawable(drawable);
mBitmap = getBitmapFromDrawable(drawable);
setupBitmapShader();
}
@Override
public void setScaleType(ScaleType scaleType) {
if (scaleType != ScaleType.CENTER_CROP) {
throw new IllegalArgumentException(String.format("ScaleType %s not supported.", scaleType));
}
}
/**
* 对于普通的view,在执行到onDraw()时,背景图已绘制完成
* <p>
* 对于ViewGroup,当它没有背景时直接调用的是dispatchDraw()方法, 而绕过了draw()方法,
* 当它有背景的时候就调用draw()方法,而draw()方法里包含了dispatchDraw()方法的调用,
*/
@Override
public void onDraw(Canvas canvas) {
if (mBitmap != null) {
if (mShape == SHAPE_CIRCLE) {
canvas.drawCircle(mViewRect.right / 2, mViewRect.bottom / 2,
Math.min(mViewRect.right, mViewRect.bottom) / 2, mBitmapPaint);
} else if (mShape == SHAPE_OVAL) {
canvas.drawOval(mViewRect, mBitmapPaint);
} else {
// canvas.drawRoundRect(mViewRect, mRoundRadius, mRoundRadius, mBitmapPaint);
mPath.reset();
mPath.addRoundRect(mViewRect, new float[]{
mRoundRadiusLeftTop, mRoundRadiusLeftTop,
mRoundRadiusRightTop, mRoundRadiusRightTop,
mRoundRadiusRightBottom, mRoundRadiusRightBottom,
mRoundRadiusLeftBottom, mRoundRadiusLeftBottom,
}, Path.Direction.CW);
canvas.drawPath(mPath, mBitmapPaint);
}
}
if (mBorderSize > 0) { // 绘制边框
if (mShape == SHAPE_CIRCLE) {
canvas.drawCircle(mViewRect.right / 2, mViewRect.bottom / 2,
Math.min(mViewRect.right, mViewRect.bottom) / 2 - mBorderSize / 2, mBorderPaint);
} else if (mShape == SHAPE_OVAL) {
canvas.drawOval(mBorderRect, mBorderPaint);
} else {
// canvas.drawRoundRect(mBorderRect, mRoundRadius, mRoundRadius, mBorderPaint);
mPath.reset();
mPath.addRoundRect(mBorderRect, new float[]{
mRoundRadiusLeftTop, mRoundRadiusLeftTop,
mRoundRadiusRightTop, mRoundRadiusRightTop,
mRoundRadiusRightBottom, mRoundRadiusRightBottom,
mRoundRadiusLeftBottom, mRoundRadiusLeftBottom,
}, Path.Direction.CW);
canvas.drawPath(mPath, mBorderPaint);
}
}
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
initRect();
setupBitmapShader();
}
// 不能在onLayout()调用invalidate(),否则导致绘制异常。(setupBitmapShader()中调用了invalidate())
@Override
protected void onLayout(boolean changed, int left, int top, int right,
int bottom) {
super.onLayout(changed, left, top, right, bottom);
// initRect();
// setupBitmapShader();
}
// 设置图片的绘制区域
private void initRect() {
mViewRect.top = 0;
mViewRect.left = 0;
mViewRect.right = getWidth(); // 宽度
mViewRect.bottom = getHeight(); // 高度
// 边框的矩形区域不能等于ImageView的矩形区域,否则边框的宽度只显示了一半
mBorderRect.top = mBorderSize / 2;
mBorderRect.left = mBorderSize / 2;
mBorderRect.right = getWidth() - mBorderSize / 2;
mBorderRect.bottom = getHeight() - mBorderSize / 2;
}
public int getShape() {
return mShape;
}
public void setShape(int shape) {
mShape = shape;
}
public float getBorderSize() {
return mBorderSize;
}
public void setBorderSize(int mBorderSize) {
this.mBorderSize = mBorderSize;
mBorderPaint.setStrokeWidth(mBorderSize);
initRect();
invalidate();
}
public int getBorderColor() {
return mBorderColor;
}
public void setBorderColor(int mBorderColor) {
this.mBorderColor = mBorderColor;
mBorderPaint.setColor(mBorderColor);
invalidate();
}
public float getRoundRadius() {
return mRoundRadius;
}
public void setRoundRadius(float mRoundRadius) {
this.mRoundRadius = mRoundRadius;
invalidate();
}
public void setRoundRadiis(float roundRadiusLeftBottom, float roundRadiusLeftTop, float roundRadiusRightBottom, float roundRadiusRightTop) {
mRoundRadiusLeftBottom = roundRadiusLeftBottom;
mRoundRadiusLeftTop = roundRadiusLeftTop;
mRoundRadiusRightBottom = roundRadiusRightBottom;
mRoundRadiusRightTop = roundRadiusRightTop;
invalidate();
}
public float[] getRoundRadiis() {
return new float[]{mRoundRadiusLeftBottom, mRoundRadiusLeftTop, mRoundRadiusRightBottom, mRoundRadiusRightTop};
}
}
工具类【SelectorAttrs】
package xiaodan.www.amor_love.Utils;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Color;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.GradientDrawable;
import android.graphics.drawable.LayerDrawable;
import android.graphics.drawable.RippleDrawable;
import android.graphics.drawable.StateListDrawable;
import android.util.AttributeSet;
import android.view.View;
import xiaodan.www.amor_love.R;
/**
* 冯人唐
*/
public class SelectorAttrs {
public static final int RECTANGLE = 0;
public static final int OVAL = 1;
public static final int LINE = 2;
public static final int RING = 3;
/**
* 直接在布局文件中直接设置selector
*
* @param context
* @param view
* @param attrs
*/
public static void obtainsAttrs(Context context, View view, AttributeSet attrs) {
//背景已经设置为StateListDrawable\RippleDrawable,则不再设置Selector
Drawable bitmapDrawable = view.getBackground();
if (bitmapDrawable instanceof StateListDrawable) {
return;
}
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) {
if (bitmapDrawable instanceof RippleDrawable) {
return;
}
}
TypedArray a = context.obtainStyledAttributes(attrs,
R.styleable.View);
// 背景图片和背景颜色互斥,只能设置其中之一
if (bitmapDrawable instanceof ColorDrawable) { // 颜色值
bitmapDrawable = null;
}
// 用于设置背景的颜色和形状
GradientDrawable colorShapeDrawable = null;
GradientDrawable colorShapeDrawablePressed = null;
GradientDrawable colorShapeDrawableSelected = null;
// 用于设置背景的图片
Drawable bitmapDrawablePressed = null;
Drawable bitmapDrawableSelected = null;
if (a.hasValue(R.styleable.View_sel_background_pressed) || a.hasValue(R.styleable.View_sel_background_border_pressed)) {
bitmapDrawablePressed = a.getDrawable(R.styleable.View_sel_background_pressed);
if (bitmapDrawablePressed instanceof ColorDrawable) {
bitmapDrawablePressed = null;
}
if (bitmapDrawablePressed == null) { // 接下来设置背景颜色
colorShapeDrawablePressed = new GradientDrawable();
}
}
if (a.hasValue(R.styleable.View_sel_background_selected) || a.hasValue(R.styleable.View_sel_background_border_selected)) {
bitmapDrawableSelected = a.getDrawable(R.styleable.View_sel_background_selected);
if (bitmapDrawableSelected instanceof ColorDrawable) {
bitmapDrawableSelected = null;
}
if (bitmapDrawableSelected == null) {
colorShapeDrawableSelected = new GradientDrawable();
}
}
// 设置背景色
int background = Color.TRANSPARENT;
if (bitmapDrawable == null) {
Drawable bg = view.getBackground();
if (bg == null && a.hasValue(R.styleable.View_sel_background)) { // 兼容旧版本属性
bg = a.getDrawable(R.styleable.View_sel_background);
}
colorShapeDrawable = new GradientDrawable();
if (bg instanceof ColorDrawable) {
background = ((ColorDrawable) bg).getColor();
colorShapeDrawable.setColor(background);
}
}
if (colorShapeDrawablePressed != null) {
colorShapeDrawablePressed.setColor(background);
}
if (colorShapeDrawableSelected != null) {
colorShapeDrawableSelected.setColor(background);
}
// 形狀
int shape = a.getInt(R.styleable.View_sel_background_shape, RECTANGLE);
if (shape == LINE) {
if (colorShapeDrawable != null) {
colorShapeDrawable.setShape(GradientDrawable.LINE);
}
if (colorShapeDrawablePressed != null) {
colorShapeDrawablePressed.setShape(GradientDrawable.LINE);
}
if (colorShapeDrawableSelected != null) {
colorShapeDrawableSelected.setShape(GradientDrawable.LINE);
}
} else if (shape == OVAL) {
if (colorShapeDrawable != null) {
colorShapeDrawable.setShape(GradientDrawable.OVAL);
}
if (colorShapeDrawablePressed != null) {
colorShapeDrawablePressed.setShape(GradientDrawable.OVAL);
}
if (colorShapeDrawableSelected != null) {
colorShapeDrawableSelected.setShape(GradientDrawable.OVAL);
}
} else if (shape == RING) {
if (colorShapeDrawable != null) {
colorShapeDrawable.setShape(GradientDrawable.RING);
}
if (colorShapeDrawablePressed != null) {
colorShapeDrawablePressed.setShape(GradientDrawable.RING);
}
if (colorShapeDrawableSelected != null) {
colorShapeDrawableSelected.setShape(GradientDrawable.RING);
}
} else {
if (colorShapeDrawable != null) {
colorShapeDrawable.setShape(GradientDrawable.RECTANGLE);
}
if (colorShapeDrawablePressed != null) {
colorShapeDrawablePressed.setShape(GradientDrawable.RECTANGLE);
}
if (colorShapeDrawableSelected != null) {
colorShapeDrawableSelected.setShape(GradientDrawable.RECTANGLE);
}
}
// 圆角
int backgroundCorners = a.getDimensionPixelOffset(R.styleable.View_sel_background_corners, 0);
final int radius = backgroundCorners;
if (colorShapeDrawable != null) {
colorShapeDrawable.setCornerRadius(backgroundCorners);
}
if (colorShapeDrawablePressed != null) {
colorShapeDrawablePressed.setCornerRadius(backgroundCorners);
}
if (colorShapeDrawableSelected != null) {
colorShapeDrawableSelected.setCornerRadius(backgroundCorners);
}
final int topLeftRadius = a.getDimensionPixelSize(
R.styleable.View_sel_background_corner_topLeft, radius);
final int topRightRadius = a.getDimensionPixelSize(
R.styleable.View_sel_background_corner_topRight, radius);
final int bottomLeftRadius = a.getDimensionPixelSize(
R.styleable.View_sel_background_corner_bottomLeft, radius);
final int bottomRightRadius = a.getDimensionPixelSize(
R.styleable.View_sel_background_corner_bottomRight, radius);
if (topLeftRadius != radius || topRightRadius != radius ||
bottomLeftRadius != radius || bottomRightRadius != radius) {
if (colorShapeDrawable != null) {
colorShapeDrawable.setCornerRadii(new float[]{
topLeftRadius, topLeftRadius,
topRightRadius, topRightRadius,
bottomRightRadius, bottomRightRadius,
bottomLeftRadius, bottomLeftRadius
});
}
if (colorShapeDrawablePressed != null) {
colorShapeDrawablePressed.setCornerRadii(new float[]{
topLeftRadius, topLeftRadius,
topRightRadius, topRightRadius,
bottomRightRadius, bottomRightRadius,
bottomLeftRadius, bottomLeftRadius
});
}
if (colorShapeDrawableSelected != null) {
colorShapeDrawableSelected.setCornerRadii(new float[]{
topLeftRadius, topLeftRadius,
topRightRadius, topRightRadius,
bottomRightRadius, bottomRightRadius,
bottomLeftRadius, bottomLeftRadius
});
}
}
// border
int backgroundBorderWidth = a.getDimensionPixelOffset(R.styleable.View_sel_background_border_width, -1);
if (backgroundBorderWidth != -1) {
if (colorShapeDrawable != null) {
colorShapeDrawable.setStroke(backgroundBorderWidth, 0);
}
if (colorShapeDrawablePressed != null) {
colorShapeDrawablePressed.setStroke(backgroundBorderWidth, 0);
}
if (colorShapeDrawableSelected != null) {
colorShapeDrawableSelected.setStroke(backgroundBorderWidth, 0);
}
}
if (a.hasValue(R.styleable.View_sel_background_border_color)) {
int backgroundBorder = a.getColor(R.styleable.View_sel_background_border_color, -1);
if (colorShapeDrawable != null) {
colorShapeDrawable.setStroke(backgroundBorderWidth, backgroundBorder);
}
if (colorShapeDrawablePressed != null) {
colorShapeDrawablePressed.setStroke(backgroundBorderWidth, backgroundBorder);
}
if (colorShapeDrawableSelected != null) {
colorShapeDrawableSelected.setStroke(backgroundBorderWidth, backgroundBorder);
}
}
// 如果没有设置背景图片,则读取背景颜色
if (colorShapeDrawablePressed != null && a.hasValue(R.styleable.View_sel_background_pressed)) {
int backgroundPressed = a.getColor(R.styleable.View_sel_background_pressed, 0);
colorShapeDrawablePressed.setColor(backgroundPressed);
}
if (colorShapeDrawablePressed != null && a.hasValue(R.styleable.View_sel_background_border_pressed)) {
int backgroundBorderPressed = a.getColor(R.styleable.View_sel_background_border_pressed, -1);
colorShapeDrawablePressed.setStroke(backgroundBorderWidth, backgroundBorderPressed);
}
if (colorShapeDrawableSelected != null && a.hasValue(R.styleable.View_sel_background_selected)) {
int backgroundSelected = a.getColor(R.styleable.View_sel_background_selected, -1);
colorShapeDrawableSelected.setColor(backgroundSelected);
}
if (colorShapeDrawableSelected != null && a.hasValue(R.styleable.View_sel_background_border_selected)) {
int backgroundBorderSelected = a.getColor(R.styleable.View_sel_background_border_selected, -1);
colorShapeDrawableSelected.setStroke(backgroundBorderWidth, backgroundBorderSelected);
}
// 设置不同状态下的显示
StateListDrawable stateListDrawable = new StateListDrawable();
// ripple属性兼容低版本(<21)
if (android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.LOLLIPOP // 低于21(5.0)版本
&& a.hasValue(R.styleable.View_sel_background_ripple)) { // 但设置了ripple,处理兼容则把ripple的颜色设为按下时的颜色
Drawable drawable = null;
if (a.hasValue(R.styleable.View_sel_background_ripple_mask)) { // 根据mask设置形状
drawable = a.getDrawable(R.styleable.View_sel_background_ripple_mask);
if (drawable instanceof ColorDrawable) { // mask为颜色类型才可以设置形状
drawable = new GradientDrawable();
parseRippleMaskShape((GradientDrawable) drawable, a);
// 以sel_background_ripple的颜色为准
((GradientDrawable) drawable).setColor(a.getColor(R.styleable.View_sel_background_ripple, 0));
} else {
drawable = a.getDrawable(R.styleable.View_sel_background_ripple);
}
} else {
drawable = a.getDrawable(R.styleable.View_sel_background_ripple);
}
// ripple效果只是在原来的pressed基础上附加波纹效果,并不会单独作为pressed状态的效果
if (colorShapeDrawablePressed != null || bitmapDrawablePressed != null) {
drawable = new LayerDrawable(new Drawable[]{
bitmapDrawablePressed != null ? bitmapDrawablePressed : colorShapeDrawablePressed,
drawable
});
} else if (bitmapDrawable != null || colorShapeDrawable != null) {
drawable = new LayerDrawable(new Drawable[]{
bitmapDrawable != null ? bitmapDrawable : colorShapeDrawable,
drawable
});
}
stateListDrawable.addState(
new int[]{android.R.attr.state_enabled, android.R.attr.state_pressed}, drawable);
} else if (colorShapeDrawablePressed != null || bitmapDrawablePressed != null) {
Drawable drawable = bitmapDrawablePressed != null ? bitmapDrawablePressed : colorShapeDrawablePressed;
stateListDrawable.addState(
new int[]{android.R.attr.state_enabled, android.R.attr.state_pressed}, drawable);
}
if (colorShapeDrawableSelected != null || bitmapDrawableSelected != null) {
Drawable drawable = bitmapDrawableSelected != null ? bitmapDrawableSelected : colorShapeDrawableSelected;
stateListDrawable.addState(
new int[]{android.R.attr.state_enabled, android.R.attr.state_selected}, drawable);
}
stateListDrawable.addState(
new int[]{},
bitmapDrawable != null ? bitmapDrawable : colorShapeDrawable);
// 设置ripple水波纹
boolean hasRipple = parseRipple(view, a,
// ripple效果只是在原来的pressed基础上附加波纹效果,并不会单独作为pressed状态的效果
(colorShapeDrawable != null || bitmapDrawable != null
|| colorShapeDrawablePressed != null || bitmapDrawablePressed != null) ?
stateListDrawable : null);
if (!hasRipple) {
view.setBackgroundDrawable(stateListDrawable);
}
a.recycle();
}
private static void parseRippleMaskShape(GradientDrawable maskShapeDrawable, TypedArray a) {
// 必须设置颜色
maskShapeDrawable.setColor(a.getColor(R.styleable.View_sel_background_ripple_mask, Color.TRANSPARENT));
// Mask形状
int shape = a.getInt(R.styleable.View_sel_background_ripple_mask_shape, RECTANGLE);
if (shape == LINE) {
maskShapeDrawable.setShape(GradientDrawable.LINE);
} else if (shape == OVAL) {
maskShapeDrawable.setShape(GradientDrawable.OVAL);
} else if (shape == RING) {
maskShapeDrawable.setShape(GradientDrawable.RING);
} else {
maskShapeDrawable.setShape(GradientDrawable.RECTANGLE);
}
// mask圆角
int backgroundCorners = a.getDimensionPixelOffset(R.styleable.View_sel_background_ripple_mask_corners, 0);
final int radius = backgroundCorners;
maskShapeDrawable.setCornerRadius(backgroundCorners);
final int topLeftRadius = a.getDimensionPixelSize(
R.styleable.View_sel_background_ripple_mask_corner_topLeft, radius);
final int topRightRadius = a.getDimensionPixelSize(
R.styleable.View_sel_background_ripple_mask_corner_topRight, radius);
final int bottomLeftRadius = a.getDimensionPixelSize(
R.styleable.View_sel_background_ripple_mask_corner_bottomLeft, radius);
final int bottomRightRadius = a.getDimensionPixelSize(
R.styleable.View_sel_background_ripple_mask_corner_bottomRight, radius);
if (topLeftRadius != radius || topRightRadius != radius ||
bottomLeftRadius != radius || bottomRightRadius != radius) {
maskShapeDrawable.setCornerRadii(new float[]{
topLeftRadius, topLeftRadius,
topRightRadius, topRightRadius,
bottomRightRadius, bottomRightRadius,
bottomLeftRadius, bottomLeftRadius
});
}
}
private static boolean parseRipple(View view, TypedArray a, Drawable content) {
// 设置ripple水波纹
boolean hasRipple = false;
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) {
if (a.hasValue(R.styleable.View_sel_background_ripple)) {
hasRipple = true;
// 设置了背景则作为ripple的contentDrawable
// 用于设置mask的形状
GradientDrawable maskShapeDrawable = null;
// 用于设置mask的图片
Drawable maskBitmapDrawable = null;
if (a.hasValue(R.styleable.View_sel_background_ripple_mask)) {
maskBitmapDrawable = a.getDrawable(R.styleable.View_sel_background_ripple_mask);
if (maskBitmapDrawable instanceof ColorDrawable) {
maskBitmapDrawable = null;
}
if (maskBitmapDrawable == null) { // 接下来设置mask形状
maskShapeDrawable = new GradientDrawable();
parseRippleMaskShape(maskShapeDrawable, a);
}
}
RippleDrawable rippleDrawable = new RippleDrawable(
a.getColorStateList(R.styleable.View_sel_background_ripple),
content, maskBitmapDrawable != null ? maskBitmapDrawable : maskShapeDrawable);
view.setBackgroundDrawable(rippleDrawable);
}
}
return hasRipple;
}
}
之后在values的文件夹下面新建“attrs.xml”文件:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="ShapeImageView">
<attr name="siv_shape" format="enum">
<enum name="rect" value="1" />
<enum name="circle" value="2" />
<enum name="oval" value="3" />
</attr>
<attr name="siv_round_radius" format="dimension" />
<attr name="siv_round_radius_leftTop" format="dimension" />
<attr name="siv_round_radius_leftBottom" format="dimension" />
<attr name="siv_round_radius_rightTop" format="dimension" />
<attr name="siv_round_radius_rightBottom" format="dimension" />
<attr name="siv_border_size" format="dimension" />
<attr name="siv_border_color" format="color" />
</declare-styleable>
<!-- 设置view相关selector熟悉-->
<declare-styleable name="View">
<attr name="injectListener" format="boolean" />
<!--该属性已过时,被废弃-->
<attr name="sel_background" format="color" />
<!-- 背景状态 -->
<attr name="sel_background_pressed" format="reference|color" />
<attr name="sel_background_selected" format="reference|color" />
<!-- 背景形状 -->
<attr name="sel_background_shape" format="enum">
<enum name="rect" value="0" />
<enum name="oval" value="1" />
<enum name="line" value="2" />
<enum name="ring" value="3" />
</attr>
<!-- 背景圆角 -->
<attr name="sel_background_corners" format="dimension" />
<attr name="sel_background_corner_topLeft" format="dimension" />
<attr name="sel_background_corner_topRight" format="dimension" />
<attr name="sel_background_corner_bottomLeft" format="dimension" />
<attr name="sel_background_corner_bottomRight" format="dimension" />
<!-- 背景边框默认状态 -->
<attr name="sel_background_border_color" format="color" />
<attr name="sel_background_border_width" format="dimension" />
<!-- 背景边框状态 -->
<attr name="sel_background_border_pressed" format="color" />
<attr name="sel_background_border_selected" format="color" />
<!-- ripple水波纹效果-->
<attr name="sel_background_ripple" format="reference|color" />
<attr name="sel_background_ripple_mask" format="reference|color" />
<!-- ripple mask形状(仅在sel_background_ripple_mask为color时生效)-->
<attr name="sel_background_ripple_mask_shape" format="enum">
<enum name="rect" value="0" />
<enum name="oval" value="1" />
<enum name="line" value="2" />
<enum name="ring" value="3" />
</attr>
<!-- ripple mask圆角 -->
<attr name="sel_background_ripple_mask_corners" format="dimension" />
<attr name="sel_background_ripple_mask_corner_topLeft" format="dimension" />
<attr name="sel_background_ripple_mask_corner_topRight" format="dimension" />
<attr name="sel_background_ripple_mask_corner_bottomLeft" format="dimension" />
<attr name="sel_background_ripple_mask_corner_bottomRight" format="dimension" />
</declare-styleable>
</resources>
大功告成,可以在布局里面用了