600字范文,内容丰富有趣,生活中的好帮手!
600字范文 > Android自定义ImageView圆角

Android自定义ImageView圆角

时间:2023-12-09 10:50:03

相关推荐

Android自定义ImageView圆角

圆角的实现方式

在Android项目中经常遇见圆角的图片的展示问题,但是很可惜,Android中的imageView并不是原生就支持圆角的,那么在Android中实现展示圆角图片的方式有几种呢?这里笔者大致总结一下分为以下几种

自定义ImageView实现圆角通过Glide的BitmapTransformation实现圆角通过fresco的SimpleDraweeView实现通过外层嵌套一层CardView实现等等…

以上,其中2/3是借助其他图片加载库实现,1是需要自行实现ImageView中圆角的绘制函数,4需要布局多一层嵌套。

按照最简单的做法这里推荐使用CardView的方式实现圆角。

但是有时候UI设计师的设计图总是不是很如开发的口味,会出现上边需要圆角,底部无圆角的设计需求,那么这是时候,直接使用自定义ImageView造一个轮子方能一劳永逸。

下面贴代码:

/*** 提供为图片添加圆角、边框、剪裁到圆形或其他形状等功能。*/public class RadiusImageView extends AppCompatImageView {private static final int DEFAULT_BORDER_COLOR = Color.GRAY;private static final Bitmap.Config BITMAP_CONFIG = Bitmap.Config.ARGB_8888;private static final int COLOR_DRAWABLE_DIMEN = 2;private boolean mIsSelected = false;private boolean mIsOval = false;private boolean mIsCircle = false;private int mBorderWidth;private int mBorderColor;private int mSelectedBorderWidth;private int mSelectedBorderColor;private int mSelectedMaskColor;private boolean mIsTouchSelectModeEnabled = true;private int mCornerRadius;private boolean roundTopLeft = true,roundTopRight= true,roundBottomRight= true,roundBottomLeft= true;private Paint mBitmapPaint;private Paint mBorderPaint;private ColorFilter mColorFilter;private ColorFilter mSelectedColorFilter;private BitmapShader mBitmapShader;private boolean mNeedResetShader = false;private RectF mRectF = new RectF();private RectF mDrawRectF = new RectF();private Path path = null;private Bitmap mBitmap;private Matrix mMatrix;private int mWidth;private int mHeight;private ScaleType mLastCalculateScaleType;@IdResprivate int placeholderImage;public RadiusImageView(Context context) {this(context, null, R.attr.RadiusImageViewStyle);}public RadiusImageView(Context context, AttributeSet attrs) {this(context, attrs, R.attr.RadiusImageViewStyle);}public RadiusImageView(Context context, AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);mBorderPaint = new Paint();mBorderPaint.setAntiAlias(true);mBorderPaint.setStyle(Paint.Style.STROKE);mMatrix = new Matrix();setScaleType(ScaleType.CENTER_CROP);TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.RadiusImageView, defStyleAttr, 0);mBorderWidth = array.getDimensionPixelSize(R.styleable.RadiusImageView_borderWidth, 0);mBorderColor = array.getColor(R.styleable.RadiusImageView_borderColor, DEFAULT_BORDER_COLOR);mSelectedBorderWidth = array.getDimensionPixelSize(R.styleable.RadiusImageView_selectedBorderWidth, mBorderWidth);mSelectedBorderColor = array.getColor(R.styleable.RadiusImageView_selectedBorderColor, mBorderColor);mSelectedMaskColor = array.getColor(R.styleable.RadiusImageView_selectedMaskColor, Color.TRANSPARENT);if (mSelectedMaskColor != Color.TRANSPARENT) {mSelectedColorFilter = new PorterDuffColorFilter(mSelectedMaskColor, PorterDuff.Mode.DARKEN);}mIsTouchSelectModeEnabled = array.getBoolean(R.styleable.RadiusImageView_isTouchSelectModeEnabled, true);mIsCircle = array.getBoolean(R.styleable.RadiusImageView_isCircle, false);if (!mIsCircle) {mIsOval = array.getBoolean(R.styleable.RadiusImageView_isOval, false);}if (!mIsOval) {mCornerRadius = array.getDimensionPixelSize(R.styleable.RadiusImageView_cornerRadius, 0);roundTopLeft = array.getBoolean(R.styleable.RadiusImageView_roundTopLeft,true);roundTopRight = array.getBoolean(R.styleable.RadiusImageView_roundTopRight,true);roundBottomRight = array.getBoolean(R.styleable.RadiusImageView_roundBottomRight,true);roundBottomLeft = array.getBoolean(R.styleable.RadiusImageView_roundBottomLeft,true);}placeholderImage = array.getResourceId(R.styleable.RadiusImageView_placeholderImage,0);array.recycle();}@Overridepublic void setAdjustViewBounds(boolean adjustViewBounds) {if (adjustViewBounds) {throw new IllegalArgumentException("不支持adjustViewBounds");}}/*** 设置边框宽度* @param borderWidth borderWidth*/public void setBorderWidth(int borderWidth) {if (mBorderWidth != borderWidth) {mBorderWidth = borderWidth;invalidate();}}/*** 设置边框颜色* @param borderColor borderColor*/public void setBorderColor(@ColorInt int borderColor) {if (mBorderColor != borderColor) {mBorderColor = borderColor;invalidate();}}/*** 设置角半径* @param cornerRadius cornerRadius*/public void setCornerRadius(int cornerRadius) {if (mCornerRadius != cornerRadius) {mCornerRadius = cornerRadius;if (!mIsCircle && !mIsOval) {invalidate();}}}/*** 设置选定边框颜色* @param selectedBorderColor selectedBorderColor*/public void setSelectedBorderColor(@ColorInt int selectedBorderColor) {if (mSelectedBorderColor != selectedBorderColor) {mSelectedBorderColor = selectedBorderColor;if (mIsSelected) {invalidate();}}}/*** 设置选定的边框宽度* @param selectedBorderWidth selectedBorderWidth*/public void setSelectedBorderWidth(int selectedBorderWidth) {if (mSelectedBorderWidth != selectedBorderWidth) {mSelectedBorderWidth = selectedBorderWidth;if (mIsSelected) {invalidate();}}}/*** 设置选定的遮罩颜色* @param selectedMaskColor selectedMaskColor*/public void setSelectedMaskColor(@ColorInt int selectedMaskColor) {if (mSelectedMaskColor != selectedMaskColor) {mSelectedMaskColor = selectedMaskColor;if (mSelectedMaskColor != Color.TRANSPARENT) {mSelectedColorFilter = new PorterDuffColorFilter(mSelectedMaskColor, PorterDuff.Mode.DARKEN);} else {mSelectedColorFilter = null;}if (mIsSelected) {invalidate();}}mSelectedMaskColor = selectedMaskColor;}/*** 是否是圆* @param isCircle 是否*/public void setCircle(boolean isCircle) {if (mIsCircle != isCircle) {mIsCircle = isCircle;requestLayout();invalidate();}}/*** 是否是椭圆* @param isOval 是否*/public void setOval(boolean isOval) {boolean forceUpdate = false;if (isOval) {if (mIsCircle) {// 必须先取消圆形mIsCircle = false;forceUpdate = true;}}if (mIsOval != isOval || forceUpdate) {mIsOval = isOval;requestLayout();invalidate();}}/*** 设置圆角的位置* @param roundTopLeft roundTopLeft* @param roundTopRight roundTopRight* @param roundBottomRight roundBottomRight* @param roundBottomLeft roundBottomLeft*/public void setRoundedLocation(boolean roundTopLeft,boolean roundTopRight,boolean roundBottomRight,boolean roundBottomLeft){if (this.roundTopLeft!=roundTopLeft || this.roundTopRight!=roundTopRight|| this.roundBottomLeft!=roundBottomLeft || this.roundBottomRight!=roundBottomRight){this.roundTopLeft = roundTopLeft;this.roundTopRight = roundTopRight;this.roundBottomRight = roundBottomRight;this.roundBottomLeft = roundBottomLeft;requestLayout();invalidate();}}public int getBorderColor() {return mBorderColor;}public int getBorderWidth() {return mBorderWidth;}public int getCornerRadius() {return mCornerRadius;}public int getSelectedBorderColor() {return mSelectedBorderColor;}public int getSelectedBorderWidth() {return mSelectedBorderWidth;}public int getSelectedMaskColor() {return mSelectedMaskColor;}public boolean isCircle() {return mIsCircle;}public boolean isOval() {return !mIsCircle && mIsOval;}@Overridepublic boolean isSelected() {return mIsSelected;}@Overridepublic void setSelected(boolean isSelected) {if (mIsSelected != isSelected) {mIsSelected = isSelected;invalidate();}}public void setTouchSelectModeEnabled(boolean touchSelectModeEnabled) {mIsTouchSelectModeEnabled = touchSelectModeEnabled;}public boolean isTouchSelectModeEnabled() {return mIsTouchSelectModeEnabled;}public void setSelectedColorFilter(ColorFilter cf) {if (mSelectedColorFilter == cf) {return;}mSelectedColorFilter = cf;if (mIsSelected) {invalidate();}}@Overridepublic void setColorFilter(ColorFilter cf) {if (mColorFilter == cf) {return;}mColorFilter = cf;if (!mIsSelected) {invalidate();}}@Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {int widthMode = MeasureSpec.getMode(widthMeasureSpec);int heightMode = MeasureSpec.getMode(heightMeasureSpec);int widthSize = MeasureSpec.getSize(widthMeasureSpec);int heightSize = MeasureSpec.getSize(heightMeasureSpec);if (widthMode == MeasureSpec.EXACTLY && heightMode == MeasureSpec.EXACTLY) {setMeasuredDimension(widthSize, heightSize);return;}if (mIsCircle) {if (widthMode == MeasureSpec.EXACTLY) {setMeasuredDimension(widthSize, widthSize);} else if (heightMode == MeasureSpec.EXACTLY) {setMeasuredDimension(heightSize, heightSize);} else {if (mBitmap == null) {setMeasuredDimension(0, 0);} else {int w = Math.min(mBitmap.getWidth(), widthSize);int h = Math.min(mBitmap.getHeight(), heightSize);int size = Math.min(w, h);setMeasuredDimension(size, size);}}return;}super.onMeasure(widthMeasureSpec, heightMeasureSpec);}@Overridepublic void setImageDrawable(Drawable drawable) {super.setImageDrawable(drawable);setupBitmap();}@Overridepublic void setImageURI(Uri uri) {super.setImageURI(uri);setupBitmap();}private Bitmap getBitmap() {Drawable drawable = getDrawable();if (drawable == null) {return null;}if (drawable instanceof BitmapDrawable) {Bitmap bitmap = ((BitmapDrawable) drawable).getBitmap();if (bitmap == null) {return null;}float bmWidth = bitmap.getWidth(), bmHeight = bitmap.getHeight();if (bmWidth == 0 || bmHeight == 0) {return null;}if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {// ensure minWidth and minHeightfloat minScaleX = getMinimumWidth() / bmWidth, minScaleY = getMinimumHeight() / bmHeight;if (minScaleX > 1 || minScaleY > 1) {float scale = Math.max(minScaleX, minScaleY);Matrix matrix = new Matrix();matrix.postScale(scale, scale);return Bitmap.createBitmap(bitmap, 0, 0, (int) bmWidth, (int) bmHeight, matrix, false);}}return bitmap;}try {Bitmap bitmap;if (drawable instanceof ColorDrawable) {bitmap = Bitmap.createBitmap(COLOR_DRAWABLE_DIMEN, COLOR_DRAWABLE_DIMEN, 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;}}public void setupBitmap() {Bitmap bm = getBitmap();if (bm == mBitmap) {return;}mBitmap = bm;if (mBitmap == null) {mBitmapShader = null;invalidate();return;}mNeedResetShader = true;mBitmapShader = new BitmapShader(mBitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);if (mBitmapPaint == null) {mBitmapPaint = new Paint();mBitmapPaint.setAntiAlias(true);}mBitmapPaint.setShader(mBitmapShader);requestLayout();invalidate();}private void updateBitmapShader() {mMatrix.reset();mNeedResetShader = false;if (mBitmapShader == null || mBitmap == null) {return;}updateMatrix(mMatrix, mBitmap, mRectF);mBitmapShader.setLocalMatrix(mMatrix);mBitmapPaint.setShader(mBitmapShader);}private void updateMatrix(@NonNull Matrix matrix, @NonNull Bitmap bitmap, RectF drawRect) {final float bmWidth = bitmap.getWidth();final float bmHeight = bitmap.getHeight();final ScaleType scaleType = getScaleType();if (scaleType == ScaleType.MATRIX) {updateScaleTypeMatrix(matrix, bitmap, drawRect);} else if (scaleType == ScaleType.CENTER) {float left = (mWidth - bmWidth) / 2;float top = (mHeight - bmHeight) / 2;matrix.postTranslate(left, top);drawRect.set(Math.max(0, left),Math.max(0, top),Math.min(left + bmWidth, mWidth),Math.min(top + bmHeight, mHeight));} else if (scaleType == ScaleType.CENTER_CROP) {float scaleX = mWidth / bmWidth, scaleY = mHeight / bmHeight;final float scale = Math.max(scaleX, scaleY);matrix.setScale(scale, scale);matrix.postTranslate(-(scale * bmWidth - mWidth) / 2, -(scale * bmHeight - mHeight) / 2);drawRect.set(0, 0, mWidth, mHeight);} else if (scaleType == ScaleType.CENTER_INSIDE) {float scaleX = mWidth / bmWidth, scaleY = mHeight / bmHeight;if (scaleX >= 1 && scaleY >= 1) {float left = (mWidth - bmWidth) / 2;float top = (mHeight - bmHeight) / 2;matrix.postTranslate(left, top);drawRect.set(left, top, left + bmWidth, top + bmHeight);} else {float scale = Math.min(scaleX, scaleY);matrix.setScale(scale, scale);float bw = bmWidth * scale, bh = bmHeight * scale;float left = (mWidth - bw) / 2;float top = (mHeight - bh) / 2;matrix.postTranslate(left, top);drawRect.set(left, top, left + bw, top + bh);}} else if (scaleType == ScaleType.FIT_XY) {float scaleX = mWidth / bmWidth, scaleY = mHeight / bmHeight;matrix.setScale(scaleX, scaleY);drawRect.set(0, 0, mWidth, mHeight);} else {float scaleX = mWidth / bmWidth, scaleY = mHeight / bmHeight;float scale = Math.min(scaleX, scaleY);matrix.setScale(scale, scale);float bw = bmWidth * scale, bh = bmHeight * scale;if (scaleType == ScaleType.FIT_START) {drawRect.set(0, 0, bw, bh);} else if (scaleType == ScaleType.FIT_CENTER) {float left = (mWidth - bw) / 2;float top = (mHeight - bh) / 2;matrix.postTranslate(left, top);drawRect.set(left, top, left + bw, top + bh);} else {matrix.postTranslate(mWidth - bw, mHeight - bh);drawRect.set(mWidth - bw, mHeight - bh, mWidth, mHeight);}}}protected void updateScaleTypeMatrix(@NonNull Matrix matrix, @NonNull Bitmap bitmap, RectF drawRect) {matrix.set(getImageMatrix());drawRect.set(0, 0, mWidth, mHeight);}private void drawBitmap(Canvas canvas, int borderWidth) {final float halfBorderWidth = borderWidth * 1.0f / 2;mBitmapPaint.setColorFilter(mIsSelected ? mSelectedColorFilter : mColorFilter);if (mIsCircle) {canvas.drawCircle(mRectF.centerX(), mRectF.centerY(), (Math.min(mRectF.width() / 2, mRectF.height() / 2)) - halfBorderWidth, mBitmapPaint);} else {mDrawRectF.left = mRectF.left + halfBorderWidth;//noinspection SuspiciousNameCombinationmDrawRectF.top = mRectF.top + halfBorderWidth;mDrawRectF.right = mRectF.right - halfBorderWidth;mDrawRectF.bottom = mRectF.bottom - halfBorderWidth;if (mIsOval) {canvas.drawOval(mDrawRectF, mBitmapPaint);} else {if (path == null){path = new Path();}path.addRoundRect(mDrawRectF,new float[] {roundTopLeft?mCornerRadius:0,roundTopLeft?mCornerRadius:0,roundTopRight?mCornerRadius:0,roundTopRight?mCornerRadius:0,roundBottomRight?mCornerRadius:0,roundBottomRight?mCornerRadius:0,roundBottomLeft?mCornerRadius:0,roundBottomLeft?mCornerRadius:0},Path.Direction.CW);canvas.drawPath(path, mBitmapPaint);}}}private void drawBorder(Canvas canvas, int borderWidth) {if (borderWidth <= 0) {return;}final float halfBorderWidth = borderWidth * 1.0f / 2;mBorderPaint.setColor(mIsSelected ? mSelectedBorderColor : mBorderColor);mBorderPaint.setStrokeWidth(borderWidth);if (mIsCircle) {canvas.drawCircle(mRectF.centerX(), mRectF.centerY(),Math.min(mRectF.width(), mRectF.height()) / 2 - halfBorderWidth, mBorderPaint);} else {mDrawRectF.left = mRectF.left + halfBorderWidth;//noinspection SuspiciousNameCombinationmDrawRectF.top = mRectF.top + halfBorderWidth;mDrawRectF.right = mRectF.right - halfBorderWidth;mDrawRectF.bottom = mRectF.bottom - halfBorderWidth;if (mIsOval) {canvas.drawOval(mDrawRectF, mBorderPaint);} else {if (path == null){path = new Path();}path.addRoundRect(mDrawRectF,new float[] {roundTopLeft?mCornerRadius:0,roundTopLeft?mCornerRadius:0,roundTopRight?mCornerRadius:0,roundTopRight?mCornerRadius:0,roundBottomRight?mCornerRadius:0,roundBottomRight?mCornerRadius:0,roundBottomLeft?mCornerRadius:0,roundBottomLeft?mCornerRadius:0},Path.Direction.CW);canvas.drawPath(path, mBitmapPaint);}}}@Overrideprotected void onDraw(Canvas canvas) {int width = getWidth(), height = getHeight();if (width <= 0 || height <= 0) {return;}int borderWidth = mIsSelected ? mSelectedBorderWidth : mBorderWidth;if (mBitmap == null || mBitmapShader == null) {drawBorder(canvas, borderWidth);return;}if (mWidth != width || mHeight != height|| mLastCalculateScaleType != getScaleType() || mNeedResetShader) {mWidth = width;mHeight = height;mLastCalculateScaleType = getScaleType();updateBitmapShader();}drawBitmap(canvas, borderWidth);drawBorder(canvas, borderWidth);}@Overridepublic boolean onTouchEvent(MotionEvent event) {if (!this.isClickable()) {this.setSelected(false);return super.onTouchEvent(event);}if (!mIsTouchSelectModeEnabled) {return super.onTouchEvent(event);}switch (event.getAction()) {case MotionEvent.ACTION_DOWN:this.setSelected(true);break;case MotionEvent.ACTION_UP:case MotionEvent.ACTION_SCROLL:case MotionEvent.ACTION_OUTSIDE:case MotionEvent.ACTION_CANCEL:this.setSelected(false);break;}return super.onTouchEvent(event);}}

自定义属性:

<!--************** RadiusImageView ****************--><declare-styleable name="RadiusImageView"><attr name="borderWidth" format="dimension"/><attr name="borderColor" format="color"/><attr name="selectedMaskColor" format="color"/><attr name="selectedBorderColor" format="color"/><attr name="selectedBorderWidth" format="dimension"/><attr name="cornerRadius" format="dimension"/><attr name="isOval" format="boolean"/><attr name="isCircle" format="boolean"/><attr name="isTouchSelectModeEnabled" format="boolean"/><!-- Round the top-left corner. Ignored if isOval isCircle is used. --><attr format="boolean" name="roundTopLeft"/><!-- Round the top-right corner. Ignored if isOval isCircle is used. --><attr format="boolean" name="roundTopRight"/><!-- Round the bottom-right corner. Ignored if isOval isCircle is used. --><attr format="boolean" name="roundBottomRight"/><!-- Round the bottom-left corner. Ignored if isOval isCircle is used. --><attr format="boolean" name="roundBottomLeft"/><!-- A drawable or color to be be used as a placeholder. --><attr format="reference" name="placeholderImage"/></declare-styleable><attr name="RadiusImageViewStyle" format="reference"/>

简单使用

<com.tao.radius.RadiusImageViewandroid:layout_width="50dp"android:layout_height="50dp"android:src="@color/black"app:cornerRadius="24dp"app:roundTopLeft="true"app:roundTopRight="true"app:roundBottomLeft="false"app:layout_constraintBottom_toBottomOf="parent"app:layout_constraintLeft_toLeftOf="parent"app:layout_constraintRight_toRightOf="parent"app:layout_constraintTop_toTopOf="parent" />

功能介绍:

支持绘制圆,椭圆,圆角,圆角控制支持四个角单独设置,边距,边距颜色,点击蒙版颜色等…

使用依赖:

//根build.gradlemaven {url 'https://jitpack.io' }//app build.gradledependencies {implementation 'com.github.huangtaoOO:RadiusImageView:Tag'}

地址:/huangtaoOO/RadiusImageView

评论回复不及时,有问题的小伙伴可以进Q群:682963103 提问

参考链接:/Tencent/QMUI_Android

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。