1. 自定义SelectableRoundedImageView类,代码如下:

package com.dfhx.project.myview;
import android.annotation.SuppressLint;
import android.content.Context;
import android.content.res.ColorStateList;
import android.content.res.Resources;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.BitmapShader;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.ColorFilter;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PixelFormat;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.Shader;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.LayerDrawable;
import android.net.Uri;
import android.util.AttributeSet;
import android.widget.ImageView;
import com.dfhx.project.R;/*** Created by JiYaRuo on 2019/10/11.* @BeUsedFor 自定义ImageView 随心所欲的改变ImageView的四个圆角角度*/
@SuppressLint("AppCompatCustomView")
public class SelectableRoundedImageView extends ImageView {public static final String TAG = "SelectableRoundedImageView";private int mResource = 0;private static final ScaleType[] sScaleTypeArray = {ScaleType.MATRIX,ScaleType.FIT_XY,ScaleType.FIT_START,ScaleType.FIT_CENTER,ScaleType.FIT_END,ScaleType.CENTER,ScaleType.CENTER_CROP,ScaleType.CENTER_INSIDE};// Set default scale type to FIT_CENTER, which is default scale type of// original ImageView.private ScaleType mScaleType = ScaleType.FIT_CENTER;private float mLeftTopCornerRadius = 0.0f;private float mRightTopCornerRadius = 0.0f;private float mLeftBottomCornerRadius = 0.0f;private float mRightBottomCornerRadius = 0.0f;private float mBorderWidth = 0.0f;private static final int DEFAULT_BORDER_COLOR = Color.BLACK;private ColorStateList mBorderColor = ColorStateList.valueOf(DEFAULT_BORDER_COLOR);private boolean isOval = false;private Drawable mDrawable;private float[] mRadii = new float[] { 0, 0, 0, 0, 0, 0, 0, 0 };public SelectableRoundedImageView(Context context) {super(context);}public SelectableRoundedImageView(Context context, AttributeSet attrs) {this(context, attrs, 0);}public SelectableRoundedImageView(Context context, AttributeSet attrs, int defStyle) {super(context, attrs, defStyle);TypedArray a = context.obtainStyledAttributes(attrs,R.styleable.SelectableRoundedImageView, defStyle, 0);final int index = a.getInt(R.styleable.SelectableRoundedImageView_android_scaleType, -1);if (index >= 0) {setScaleType(sScaleTypeArray[index]);}mLeftTopCornerRadius = a.getDimensionPixelSize(R.styleable.SelectableRoundedImageView_sriv_left_top_corner_radius, 0);mRightTopCornerRadius = a.getDimensionPixelSize(R.styleable.SelectableRoundedImageView_sriv_right_top_corner_radius, 0);mLeftBottomCornerRadius = a.getDimensionPixelSize(R.styleable.SelectableRoundedImageView_sriv_left_bottom_corner_radius, 0);mRightBottomCornerRadius = a.getDimensionPixelSize(R.styleable.SelectableRoundedImageView_sriv_right_bottom_corner_radius, 0);if (mLeftTopCornerRadius < 0.0f || mRightTopCornerRadius < 0.0f|| mLeftBottomCornerRadius < 0.0f || mRightBottomCornerRadius < 0.0f) {throw new IllegalArgumentException("radius values cannot be negative.");}mRadii = new float[] {mLeftTopCornerRadius, mLeftTopCornerRadius,mRightTopCornerRadius, mRightTopCornerRadius,mRightBottomCornerRadius, mRightBottomCornerRadius,mLeftBottomCornerRadius, mLeftBottomCornerRadius};mBorderWidth = a.getDimensionPixelSize(R.styleable.SelectableRoundedImageView_sriv_border_width, 0);if (mBorderWidth < 0) {throw new IllegalArgumentException("border width cannot be negative.");}mBorderColor = a.getColorStateList(R.styleable.SelectableRoundedImageView_sriv_border_color);if (mBorderColor == null) {mBorderColor = ColorStateList.valueOf(DEFAULT_BORDER_COLOR);}isOval = a.getBoolean(R.styleable.SelectableRoundedImageView_sriv_oval, false);a.recycle();updateDrawable();}@Overrideprotected void drawableStateChanged() {super.drawableStateChanged();invalidate();}@Overridepublic ScaleType getScaleType() {return mScaleType;}@Overridepublic void setScaleType(ScaleType scaleType) {super.setScaleType(scaleType);mScaleType = scaleType;updateDrawable();}@Overridepublic void setImageDrawable(Drawable drawable) {mResource = 0;mDrawable = SelectableRoundedCornerDrawable.fromDrawable(drawable, getResources());super.setImageDrawable(mDrawable);updateDrawable();}@Overridepublic void setImageBitmap(Bitmap bm) {mResource = 0;mDrawable = SelectableRoundedCornerDrawable.fromBitmap(bm, getResources());super.setImageDrawable(mDrawable);updateDrawable();}@Overridepublic void setImageResource(int resId) {if (mResource != resId) {mResource = resId;mDrawable = resolveResource();super.setImageDrawable(mDrawable);updateDrawable();}}@Overridepublic void setImageURI(Uri uri) {super.setImageURI(uri);setImageDrawable(getDrawable());}private Drawable resolveResource() {Resources rsrc = getResources();if (rsrc == null) {return null;}Drawable d = null;if (mResource != 0) {try {d = rsrc.getDrawable(mResource);} catch (Exception e) {
//                Log.w(TAG, "Unable to find resource: " + mResource, e);// Don't try again.mResource = 0;}}return SelectableRoundedCornerDrawable.fromDrawable(d, getResources());}private void updateDrawable() {if (mDrawable == null) {return;}((SelectableRoundedCornerDrawable) mDrawable).setScaleType(mScaleType);((SelectableRoundedCornerDrawable) mDrawable).setCornerRadii(mRadii);((SelectableRoundedCornerDrawable) mDrawable).setBorderWidth(mBorderWidth);((SelectableRoundedCornerDrawable) mDrawable).setBorderColor(mBorderColor);((SelectableRoundedCornerDrawable) mDrawable).setOval(isOval);}public float getCornerRadius() {return mLeftTopCornerRadius;}/*** Set radii for each corner.** @param leftTop The desired radius for left-top corner in dip.* @param rightTop The desired desired radius for right-top corner in dip.* @param leftBottom The desired radius for left-bottom corner in dip.* @param rightBottom The desired radius for right-bottom corner in dip.**/public void setCornerRadiiDP(float leftTop, float rightTop, float leftBottom, float rightBottom) {final float density = getResources().getDisplayMetrics().density;final float lt = leftTop * density;final float rt = rightTop * density;final float lb = leftBottom * density;final float rb = rightBottom * density;mRadii = new float[] { lt, lt, rt, rt, rb, rb, lb, lb };updateDrawable();}public float getBorderWidth() {return mBorderWidth;}/*** Set border width.** @param width*            The desired width in dip.*/public void setBorderWidthDP(float width) {float scaledWidth = getResources().getDisplayMetrics().density * width;if (mBorderWidth == scaledWidth) {return;}mBorderWidth = scaledWidth;updateDrawable();invalidate();}public int getBorderColor() {return mBorderColor.getDefaultColor();}public void setBorderColor(int color) {setBorderColor(ColorStateList.valueOf(color));}public ColorStateList getBorderColors() {return mBorderColor;}public void setBorderColor(ColorStateList colors) {if (mBorderColor.equals(colors)) {return;}mBorderColor = (colors != null) ? colors : ColorStateList.valueOf(DEFAULT_BORDER_COLOR);updateDrawable();if (mBorderWidth > 0) {invalidate();}}public boolean isOval() {return isOval;}public void setOval(boolean oval) {isOval = oval;updateDrawable();invalidate();}static class SelectableRoundedCornerDrawable extends Drawable {private static final String TAG = "SelectableRoundedCornerDrawable";private static final int DEFAULT_BORDER_COLOR = Color.BLACK;private RectF mBounds = new RectF();private RectF mBorderBounds = new RectF();private final RectF mBitmapRect = new RectF();private final int mBitmapWidth;private final int mBitmapHeight;private final Paint mBitmapPaint;private final Paint mBorderPaint;private BitmapShader mBitmapShader;private float[] mRadii = new float[] { 0, 0, 0, 0, 0, 0, 0, 0 };private float[] mBorderRadii = new float[] { 0, 0, 0, 0, 0, 0, 0, 0 };private boolean mOval = false;private float mBorderWidth = 0;private ColorStateList mBorderColor = ColorStateList.valueOf(DEFAULT_BORDER_COLOR);// Set default scale type to FIT_CENTER, which is default scale type of// original ImageView.private ScaleType mScaleType = ScaleType.FIT_CENTER;private Path mPath = new Path();private Bitmap mBitmap;private boolean mBoundsConfigured = false;public SelectableRoundedCornerDrawable(Bitmap bitmap, Resources r) {mBitmap = bitmap;mBitmapShader = new BitmapShader(bitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);if (bitmap != null) {mBitmapWidth = bitmap.getScaledWidth(r.getDisplayMetrics());mBitmapHeight = bitmap.getScaledHeight(r.getDisplayMetrics());} else {mBitmapWidth = mBitmapHeight = -1;}mBitmapRect.set(0, 0, mBitmapWidth, mBitmapHeight);mBitmapPaint = new Paint(Paint.ANTI_ALIAS_FLAG);mBitmapPaint.setStyle(Paint.Style.FILL);mBitmapPaint.setShader(mBitmapShader);mBorderPaint = new Paint(Paint.ANTI_ALIAS_FLAG);mBorderPaint.setStyle(Paint.Style.STROKE);mBorderPaint.setColor(mBorderColor.getColorForState(getState(), DEFAULT_BORDER_COLOR));mBorderPaint.setStrokeWidth(mBorderWidth);}public static SelectableRoundedCornerDrawable fromBitmap(Bitmap bitmap, Resources r) {if (bitmap != null) {return new SelectableRoundedCornerDrawable(bitmap, r);} else {return null;}}public static Drawable fromDrawable(Drawable drawable, Resources r) {if (drawable != null) {if (drawable instanceof SelectableRoundedCornerDrawable) {return drawable;} else if (drawable instanceof LayerDrawable) {LayerDrawable ld = (LayerDrawable) drawable;final int num = ld.getNumberOfLayers();for (int i = 0; i < num; i++) {Drawable d = ld.getDrawable(i);ld.setDrawableByLayerId(ld.getId(i), fromDrawable(d, r));}return ld;}Bitmap bm = drawableToBitmap(drawable);if (bm != null) {return new SelectableRoundedCornerDrawable(bm, r);} else {
//                    Log.w(TAG, "Failed to create bitmap from drawable!");}}return drawable;}public static Bitmap drawableToBitmap(Drawable drawable) {if (drawable == null) {return null;}if (drawable instanceof BitmapDrawable) {return ((BitmapDrawable) drawable).getBitmap();}Bitmap bitmap;int width = Math.max(drawable.getIntrinsicWidth(), 2);int height = Math.max(drawable.getIntrinsicHeight(), 2);try {bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);Canvas canvas = new Canvas(bitmap);drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());drawable.draw(canvas);} catch (IllegalArgumentException e) {e.printStackTrace();bitmap = null;}return bitmap;}@Overridepublic boolean isStateful() {return mBorderColor.isStateful();}@Overrideprotected boolean onStateChange(int[] state) {int newColor = mBorderColor.getColorForState(state, 0);if (mBorderPaint.getColor() != newColor) {mBorderPaint.setColor(newColor);return true;} else {return super.onStateChange(state);}}private void configureBounds(Canvas canvas) {// I have discovered a truly marvelous explanation of this,// which this comment space is too narrow to contain. :)// If you want to understand what's going on here,// See http://www.joooooooooonhokim.com/?p=289Rect clipBounds = canvas.getClipBounds();Matrix canvasMatrix = canvas.getMatrix();if (ScaleType.CENTER == mScaleType) {mBounds.set(clipBounds);} else if (ScaleType.CENTER_CROP == mScaleType) {applyScaleToRadii(canvasMatrix);mBounds.set(clipBounds);} else if (ScaleType.FIT_XY == mScaleType) {Matrix m = new Matrix();m.setRectToRect(mBitmapRect, new RectF(clipBounds), Matrix.ScaleToFit.FILL);mBitmapShader.setLocalMatrix(m);mBounds.set(clipBounds);} else if (ScaleType.FIT_START == mScaleType || ScaleType.FIT_END == mScaleType|| ScaleType.FIT_CENTER == mScaleType || ScaleType.CENTER_INSIDE == mScaleType) {applyScaleToRadii(canvasMatrix);mBounds.set(mBitmapRect);} else if (ScaleType.MATRIX == mScaleType) {applyScaleToRadii(canvasMatrix);mBounds.set(mBitmapRect);}}private void applyScaleToRadii(Matrix m) {float[] values = new float[9];m.getValues(values);for (int i = 0; i < mRadii.length; i++) {mRadii[i] = mRadii[i] / values[0];}}private void adjustCanvasForBorder(Canvas canvas) {Matrix canvasMatrix = canvas.getMatrix();final float[] values = new float[9];canvasMatrix.getValues(values);final float scaleFactorX = values[0];final float scaleFactorY = values[4];final float translateX = values[2];final float translateY = values[5];final float newScaleX = mBounds.width()/ (mBounds.width() + mBorderWidth + mBorderWidth);final float newScaleY = mBounds.height()/ (mBounds.height() + mBorderWidth + mBorderWidth);canvas.scale(newScaleX, newScaleY);if (ScaleType.FIT_START == mScaleType || ScaleType.FIT_END == mScaleType|| ScaleType.FIT_XY == mScaleType || ScaleType.FIT_CENTER == mScaleType|| ScaleType.CENTER_INSIDE == mScaleType || ScaleType.MATRIX == mScaleType) {canvas.translate(mBorderWidth, mBorderWidth);} else if (ScaleType.CENTER == mScaleType || ScaleType.CENTER_CROP == mScaleType) {// First, make translate values to 0canvas.translate(-translateX / (newScaleX * scaleFactorX),-translateY / (newScaleY * scaleFactorY));// Then, set the final translate values.canvas.translate(-(mBounds.left - mBorderWidth), -(mBounds.top - mBorderWidth));}}private void adjustBorderWidthAndBorderBounds(Canvas canvas) {Matrix canvasMatrix = canvas.getMatrix();final float[] values = new float[9];canvasMatrix.getValues(values);final float scaleFactor = values[0];float viewWidth = mBounds.width() * scaleFactor;mBorderWidth = (mBorderWidth * mBounds.width()) / (viewWidth - (2 * mBorderWidth));mBorderPaint.setStrokeWidth(mBorderWidth);mBorderBounds.set(mBounds);mBorderBounds.inset(- mBorderWidth / 2, - mBorderWidth / 2);}private void setBorderRadii() {for (int i = 0; i < mRadii.length; i++) {if (mRadii[i] > 0) {mBorderRadii[i] = mRadii[i];mRadii[i] = mRadii[i] - mBorderWidth;}}}@Overridepublic void draw(Canvas canvas) {canvas.save();if (!mBoundsConfigured) {configureBounds(canvas);if (mBorderWidth > 0) {adjustBorderWidthAndBorderBounds(canvas);setBorderRadii();}mBoundsConfigured = true;}if (mOval) {if (mBorderWidth > 0) {adjustCanvasForBorder(canvas);mPath.addOval(mBounds, Path.Direction.CW);canvas.drawPath(mPath, mBitmapPaint);mPath.reset();mPath.addOval(mBorderBounds, Path.Direction.CW);canvas.drawPath(mPath, mBorderPaint);} else {mPath.addOval(mBounds, Path.Direction.CW);canvas.drawPath(mPath, mBitmapPaint);}} else {if (mBorderWidth > 0) {adjustCanvasForBorder(canvas);mPath.addRoundRect(mBounds, mRadii, Path.Direction.CW);canvas.drawPath(mPath, mBitmapPaint);mPath.reset();mPath.addRoundRect(mBorderBounds, mBorderRadii, Path.Direction.CW);canvas.drawPath(mPath, mBorderPaint);} else {mPath.addRoundRect(mBounds, mRadii, Path.Direction.CW);canvas.drawPath(mPath, mBitmapPaint);}}canvas.restore();}public void setCornerRadii(float[] radii) {if (radii == null)return;if (radii.length != 8) {throw new ArrayIndexOutOfBoundsException("radii[] needs 8 values");}for (int i = 0; i < radii.length; i++) {mRadii[i] = radii[i];}}@Overridepublic int getOpacity() {return (mBitmap == null || mBitmap.hasAlpha() || mBitmapPaint.getAlpha() < 255) ? PixelFormat.TRANSLUCENT: PixelFormat.OPAQUE;}@Overridepublic void setAlpha(int alpha) {mBitmapPaint.setAlpha(alpha);invalidateSelf();}@Overridepublic void setColorFilter(ColorFilter cf) {mBitmapPaint.setColorFilter(cf);invalidateSelf();}@Overridepublic void setDither(boolean dither) {mBitmapPaint.setDither(dither);invalidateSelf();}@Overridepublic void setFilterBitmap(boolean filter) {mBitmapPaint.setFilterBitmap(filter);invalidateSelf();}@Overridepublic int getIntrinsicWidth() {return mBitmapWidth;}@Overridepublic int getIntrinsicHeight() {return mBitmapHeight;}public float getBorderWidth() {return mBorderWidth;}public void setBorderWidth(float width) {mBorderWidth = width;mBorderPaint.setStrokeWidth(width);}public int getBorderColor() {return mBorderColor.getDefaultColor();}public void setBorderColor(int color) {setBorderColor(ColorStateList.valueOf(color));}public ColorStateList getBorderColors() {return mBorderColor;}/*** Controls border color of this ImageView.** @param colors*            The desired border color. If it's null, no border will be*            drawn.**/public void setBorderColor(ColorStateList colors) {if (colors == null) {mBorderWidth = 0;mBorderColor = ColorStateList.valueOf(Color.TRANSPARENT);mBorderPaint.setColor(Color.TRANSPARENT);} else {mBorderColor = colors;mBorderPaint.setColor(mBorderColor.getColorForState(getState(),DEFAULT_BORDER_COLOR));}}public boolean isOval() {return mOval;}public void setOval(boolean oval) {mOval = oval;}public ScaleType getScaleType() {return mScaleType;}public void setScaleType(ScaleType scaleType) {if (scaleType == null) {return;}mScaleType = scaleType;}}
}

2.样式代码:res/values下的styles.xml中添加

<!-- ImageView四个圆角角度自定义-->
<declare-styleable name="SelectableRoundedImageView"><attr name="sriv_left_top_corner_radius" format="dimension" /><attr name="sriv_right_top_corner_radius" format="dimension" /><attr name="sriv_left_bottom_corner_radius" format="dimension" /><attr name="sriv_right_bottom_corner_radius" format="dimension" /><attr name="sriv_border_width" format="dimension" /><attr name="sriv_border_color" format="color" /><attr name="sriv_oval" format="boolean" /><attr name="android:scaleType" /></declare-styleable>

Android—ImageView—自定义四个圆角角度相关推荐

  1. android 布局圆变椭圆,Android实现自定义圆形、圆角和椭圆ImageView(使用Xfermode图形渲染方法)...

    一:简介: 在上一篇 这样可以省很多事情,比如测量步骤,以及不需要自己去写设置图片的方法,本文使用Xfermode模式中的DST_IN模式来实现要达到的效果,当然大家也可以采用其他的模式,比如SRC_ ...

  2. Android ImageView到底怎么设置圆角图片?背景圆角?控件圆角?图片圆角?占位图圆角?

    前言 在我们实际开发应用的过程中,我想大家或多或少都遇到过需要加载圆角图片的场景,还有一些图片是四周圆角不对称,异性圆角等等情况. 我们可能会去网上或Github上搜索一些RoundImageView ...

  3. Android ImageView 四个角自定义角度,以及角度的变换

    背景: 在正常开发过程中,我们经常会发现一些图片有各种各样的显示,有圆角.直角.圆形.不规则图形等?比较常见的是圆形,还有圆角.今天我们将讲述圆角.四个角不同度数以及通过圆角巧妙变成圆形 1.如果大家 ...

  4. android Imageview 随心所欲定制四个圆角

    android Imageview 随心所欲定制四个圆角 实现效果图如下 一个四个圆角的view 包含一个上面两个圆角的Imageview ,这样的设计比较美观,但是这样在安卓端实现让我思考了一段时间 ...

  5. Android实现自定义圆角边框渐变

    1.定义全部圆角的通用接口 public interface IRadiusLayout {int DEFAULT_RADIUS = 0; // 默认没有圆角int SOLID_TYPE_SOLID ...

  6. android自定义listview实现圆角

    在项目中我们会经常遇到这种圆角效果,因为直角的看起来确实不那么雅观,可能大家会想到用图片实现,试想上中下要分别做三张图片,这样既会是自己的项目增大也会增加内存使用量,所以使用shape来实现不失为一种 ...

  7. 【和UI斗智斗勇的日子】Android实现一个只有四个圆角有边框的边框

    加一个边框 如下图所示,这是安卓中最基础的一个边框 它的代码是这样实现的 <shape xmlns:android="http://schemas.android.com/apk/re ...

  8. Android 自定义View 圆形圆角图片

    [Android 自定义View 圆形圆角图片] 基于Xfermode 实现 1.概述 在很久以前也写过一个利用Xfermode 实现圆形.圆角图片的(Android 完美实现图片圆角和圆形(对实现进 ...

  9. Android之自定义View实现带4圆角或者2圆角的效果

    1 问题 实现任意view经过自定义带4圆角或者2圆角的效果 2 原理 1) 实现view 4圆角 我们只需要把左边的图嵌入到右边里面去,最终显示左边的图就行. 2) 实现view上2圆角 我们只需要 ...

最新文章

  1. Linux权限管理(suid euid)
  2. mini2440 之——LED简单控制(裸机) c与汇编
  3. LeetCode-175. 组合两个表(SQL语句中的LEFT JOIN)
  4. linux存储库rep 61082,安装informatic过程中的错误
  5. [css] 清除浮动的方式有哪些及优缺点?
  6. 面向对象软件设计原则(一) —— 引子
  7. 数据仓库 和挖掘的步骤 - oracle
  8. ubuntu两张网卡时的网络设置
  9. 讨教大学|ASQ黑带考试通关秘籍,纯知识干货分享
  10. 《如何撰写和发表SCI期刊论文》阅读笔记
  11. 从零开始学习SEO的基础概念
  12. 女子发现前夫外遇索要2000万
  13. 全国地区+邮编的数据库脚本
  14. android 自动替换资源文件,简单高效的实现Android App全局字体替换
  15. linux复制与粘贴操作的快捷键
  16. 经典代码-request请求获取参数(post和get两种方式)
  17. 暖暖环游世界显示服务器异常,暖暖环游世界客服常见问题汇总
  18. 【高等数学】常用的三角函数与反三角函数
  19. ROS入门——胡春旭老师《机器人开发实践》在ROS-Melodic下的编译
  20. 如何通过病毒营销打造爆款产品

热门文章

  1. 怎样修复小米服务器,小米手机删除的视频想要恢复?那你一定不能错过这些实用技巧...
  2. angular.js 错误: Error [$injector:unpr] 原因
  3. WPS广告投放的优势!WPS广告投放的展现形式!
  4. Teach yourself Programing in Ten Years(翻译+原文链接)
  5. Gerrit no Verified 在最新的2.7版本之后添加Verified
  6. eem二级c语言题库哪种比较好,EEM18DCAD边缘板连接器供应【科美奇科技】Sullins华南地区渠道商...
  7. 帝国cms php循环,帝国CMS listshowclass循环栏目标签
  8. C++primer十万字笔记 第九章 顺序容器
  9. html怎么放边框,html怎么设置边框
  10. 聊聊关于“破圈”的话题