圆边框android,android 9.0圆形 带边框 图片内容 超出圆形边框

作者更新太慢了。。Bug只能自己动手修了(有没有影响到其他功能需要大家再认真测下 我试是没问题的~)

==========================分割线==============================

一、问题出在哪?

控件用到了 Xfermode这个东西,我试了下。

1、先画一个circle(非bitmap),然后setXfermode 为Src_In,再画一个bitmap(图片的),正常显示。

2、先画一个bitmap(图片的),然后setXfermode 为Dsr_In,再画circle。异常。(大概看下来代码 作者应该用的这一种画法)

第一种:先画circle 在canvas那层,再画Bitmap新一层,中间Xfermode

第二种: 先画bitmap一层,再画circle还是原来那层 中间Xfermode

=============================上代码======================

package com.othershe.library;

import android.content.Context;

import android.content.res.TypedArray;

import android.graphics.Bitmap;

import android.graphics.Canvas;

import android.graphics.Color;

import android.graphics.Matrix;

import android.graphics.Paint;

import android.graphics.Path;

import android.graphics.PorterDuff;

import android.graphics.PorterDuffXfermode;

import android.graphics.RectF;

import android.graphics.Xfermode;

import android.graphics.drawable.BitmapDrawable;

import android.graphics.drawable.Drawable;

import android.support.annotation.ColorInt;

import android.support.annotation.Nullable;

import android.support.v7.widget.AppCompatImageView;

import android.util.AttributeSet;

public class NiceImageView extends AppCompatImageView {

private Context context;

private boolean isCircle; // 是否显示为圆形,如果为圆形则设置的corner无效

private boolean isCoverSrc; // border、inner_border是否覆盖图片

private int borderWidth; // 边框宽度

private int borderColor = Color.WHITE; // 边框颜色

private int innerBorderWidth; // 内层边框宽度

private int innerBorderColor = Color.WHITE; // 内层边框充色

private int cornerRadius; // 统一设置圆角半径,优先级高于单独设置每个角的半径

private int cornerTopLeftRadius; // 左上角圆角半径

private int cornerTopRightRadius; // 右上角圆角半径

private int cornerBottomLeftRadius; // 左下角圆角半径

private int cornerBottomRightRadius; // 右下角圆角半径

private int maskColor; // 遮罩颜色

private Xfermode xfermode;

private int width;

private int height;

private float radius;

private float[] borderRadii;

private float[] srcRadii;

private RectF srcRectF; // 图片占的矩形区域

private RectF borderRectF; // 边框的矩形区域

private Path path = new Path();

private Paint paint = new Paint();

public NiceImageView(Context context) {

this(context, null);

}

public NiceImageView(Context context, @Nullable AttributeSet attrs) {

this(context, attrs, 0);

}

public NiceImageView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {

super(context, attrs, defStyleAttr);

this.context = context;

TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.NiceImageView, 0, 0);

for (int i = 0; i < ta.getIndexCount(); i++) {

int attr = ta.getIndex(i);

if (attr == R.styleable.NiceImageView_is_cover_src) {

isCoverSrc = ta.getBoolean(attr, isCoverSrc);

} else if (attr == R.styleable.NiceImageView_is_circle) {

isCircle = ta.getBoolean(attr, isCircle);

} else if (attr == R.styleable.NiceImageView_border_width) {

borderWidth = ta.getDimensionPixelSize(attr, borderWidth);

} else if (attr == R.styleable.NiceImageView_border_color) {

borderColor = ta.getColor(attr, borderColor);

} else if (attr == R.styleable.NiceImageView_inner_border_width) {

innerBorderWidth = ta.getDimensionPixelSize(attr, innerBorderWidth);

} else if (attr == R.styleable.NiceImageView_inner_border_color) {

innerBorderColor = ta.getColor(attr, innerBorderColor);

} else if (attr == R.styleable.NiceImageView_corner_radius) {

cornerRadius = ta.getDimensionPixelSize(attr, cornerRadius);

} else if (attr == R.styleable.NiceImageView_corner_top_left_radius) {

cornerTopLeftRadius = ta.getDimensionPixelSize(attr, cornerTopLeftRadius);

} else if (attr == R.styleable.NiceImageView_corner_top_right_radius) {

cornerTopRightRadius = ta.getDimensionPixelSize(attr, cornerTopRightRadius);

} else if (attr == R.styleable.NiceImageView_corner_bottom_left_radius) {

cornerBottomLeftRadius = ta.getDimensionPixelSize(attr, cornerBottomLeftRadius);

} else if (attr == R.styleable.NiceImageView_corner_bottom_right_radius) {

cornerBottomRightRadius = ta.getDimensionPixelSize(attr, cornerBottomRightRadius);

} else if (attr == R.styleable.NiceImageView_mask_color) {

maskColor = ta.getColor(attr, maskColor);

}

}

ta.recycle();

borderRadii = new float[8];

srcRadii = new float[8];

borderRectF = new RectF();

srcRectF = new RectF();

xfermode = new PorterDuffXfermode(PorterDuff.Mode.SRC_IN);

calculateRadii();

clearInnerBorderWidth();

}

@Override

protected void onSizeChanged(int w, int h, int oldw, int oldh) {

super.onSizeChanged(w, h, oldw, oldh);

width = w;

height = h;

initBorderRectF();

initSrcRectF();

}

//替换掉NICEIAMGE类中的这个方法就行了

@Override

protected void onDraw(Canvas canvas) {

// 使用图形混合模式来显示指定区域的图片

canvas.saveLayer(0, 0, getWidth(), getHeight(), null, Canvas.ALL_SAVE_FLAG);

Drawable drawable = getDrawable();

if (drawable == null) {

super.onDraw(canvas);

return;

}

paint.reset();

path.reset();

if (!isCoverSrc) {

float sx = 1.0f * (width - 2 * borderWidth - 2 * innerBorderWidth) / width;

float sy = 1.0f * (height - 2 * borderWidth - 2 * innerBorderWidth) / height;

// 缩小画布,使图片内容不被border、padding覆盖

canvas.scale(sx, sy, width / 2.0f, height / 2.0f);

}

if (isCircle) {

path.addCircle(width / 2.0f, height / 2.0f, radius, Path.Direction.CCW);

} else {

path.addRoundRect(srcRectF, srcRadii, Path.Direction.CCW);

}

paint.setAntiAlias(true);

paint.setStyle(Paint.Style.FILL);

canvas.drawPath(path, paint);

paint.setXfermode(xfermode);

canvas.drawBitmap(zoomDrawable(drawable), 0, 0, paint);

paint.setXfermode(null);

// 绘制遮罩

if (maskColor != 0) {

paint.setColor(maskColor);

canvas.drawPath(path, paint);

}

// 恢复画布

canvas.restore();

// 绘制边框

drawBorders(canvas);

}

private void drawBorders(Canvas canvas) {

if (isCircle) {

if (borderWidth > 0) {

drawCircleBorder(canvas, borderWidth, borderColor, radius - borderWidth / 2.0f);

}

if (innerBorderWidth > 0) {

drawCircleBorder(canvas, innerBorderWidth, innerBorderColor, radius - borderWidth - innerBorderWidth / 2.0f);

}

} else {

if (borderWidth > 0) {

drawRectFBorder(canvas, borderWidth, borderColor, borderRectF, borderRadii);

}

}

}

private void drawCircleBorder(Canvas canvas, int borderWidth, int borderColor, float radius) {

initBorderPaint(borderWidth, borderColor);

path.addCircle(width / 2.0f, height / 2.0f, radius, Path.Direction.CCW);

canvas.drawPath(path, paint);

}

private void drawRectFBorder(Canvas canvas, int borderWidth, int borderColor, RectF rectF, float[] radii) {

initBorderPaint(borderWidth, borderColor);

path.addRoundRect(rectF, radii, Path.Direction.CCW);

canvas.drawPath(path, paint);

}

private void initBorderPaint(int borderWidth, int borderColor) {

path.reset();

paint.setStrokeWidth(borderWidth);

paint.setColor(borderColor);

paint.setStyle(Paint.Style.STROKE);

}

/**

* 计算外边框的RectF

*/

private void initBorderRectF() {

if (!isCircle) {

borderRectF.set(borderWidth / 2.0f, borderWidth / 2.0f, width - borderWidth / 2.0f, height - borderWidth / 2.0f);

}

}

/**

* 计算图片原始区域的RectF

*/

private void initSrcRectF() {

if (isCircle) {

radius = Math.min(width, height) / 2.0f;

srcRectF.set(width / 2.0f - radius, height / 2.0f - radius, width / 2.0f + radius, height / 2.0f + radius);

} else {

srcRectF.set(0, 0, width, height);

if (isCoverSrc) {

srcRectF = borderRectF;

}

}

}

/**

* 计算RectF的圆角半径

*/

private void calculateRadii() {

if (isCircle) {

return;

}

if (cornerRadius > 0) {

for (int i = 0; i < borderRadii.length; i++) {

borderRadii[i] = cornerRadius;

srcRadii[i] = cornerRadius - borderWidth / 2.0f;

}

} else {

borderRadii[0] = borderRadii[1] = cornerTopLeftRadius;

borderRadii[2] = borderRadii[3] = cornerTopRightRadius;

borderRadii[4] = borderRadii[5] = cornerBottomRightRadius;

borderRadii[6] = borderRadii[7] = cornerBottomLeftRadius;

srcRadii[0] = srcRadii[1] = cornerTopLeftRadius - borderWidth / 2.0f;

srcRadii[2] = srcRadii[3] = cornerTopRightRadius - borderWidth / 2.0f;

srcRadii[4] = srcRadii[5] = cornerBottomRightRadius - borderWidth / 2.0f;

srcRadii[6] = srcRadii[7] = cornerBottomLeftRadius - borderWidth / 2.0f;

}

}

private void calculateRadiiAndRectF(boolean reset) {

if (reset) {

cornerRadius = 0;

}

calculateRadii();

initBorderRectF();

invalidate();

}

/**

* 目前圆角矩形情况下不支持inner_border,需要将其置0

*/

private void clearInnerBorderWidth() {

if (!isCircle) {

this.innerBorderWidth = 0;

}

}

public void isCoverSrc(boolean isCoverSrc) {

this.isCoverSrc = isCoverSrc;

initSrcRectF();

invalidate();

}

public void isCircle(boolean isCircle) {

this.isCircle = isCircle;

clearInnerBorderWidth();

initSrcRectF();

invalidate();

}

public void setBorderWidth(int borderWidth) {

this.borderWidth = Utils.dp2px(context, borderWidth);

calculateRadiiAndRectF(false);

}

public void setBorderColor(@ColorInt int borderColor) {

this.borderColor = borderColor;

invalidate();

}

public void setInnerBorderWidth(int innerBorderWidth) {

this.innerBorderWidth = Utils.dp2px(context, innerBorderWidth);

clearInnerBorderWidth();

invalidate();

}

public void setInnerBorderColor(@ColorInt int innerBorderColor) {

this.innerBorderColor = innerBorderColor;

invalidate();

}

public void setCornerRadius(int cornerRadius) {

this.cornerRadius = Utils.dp2px(context, cornerRadius);

calculateRadiiAndRectF(false);

}

public void setCornerTopLeftRadius(int cornerTopLeftRadius) {

this.cornerTopLeftRadius = Utils.dp2px(context, cornerTopLeftRadius);

calculateRadiiAndRectF(true);

}

public void setCornerTopRightRadius(int cornerTopRightRadius) {

this.cornerTopRightRadius = Utils.dp2px(context, cornerTopRightRadius);

calculateRadiiAndRectF(true);

}

public void setCornerBottomLeftRadius(int cornerBottomLeftRadius) {

this.cornerBottomLeftRadius = Utils.dp2px(context, cornerBottomLeftRadius);

calculateRadiiAndRectF(true);

}

public void setCornerBottomRightRadius(int cornerBottomRightRadius) {

this.cornerBottomRightRadius = Utils.dp2px(context, cornerBottomRightRadius);

calculateRadiiAndRectF(true);

}

public void setMaskColor(@ColorInt int maskColor) {

this.maskColor = maskColor;

invalidate();

}

private Bitmap drawableToBitamp(Drawable drawable) {

if (drawable instanceof BitmapDrawable) {

BitmapDrawable bd = (BitmapDrawable) drawable;

return bd.getBitmap();

}

// 设置为颜色时,获取的drawable宽高会有问题,所有当为颜色时候获取控件的宽高

int w = drawable.getIntrinsicWidth() <= 0 ? getWidth() : drawable.getIntrinsicWidth();

int h = drawable.getIntrinsicHeight() <= 0 ? getHeight() : drawable.getIntrinsicHeight();

Bitmap bitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);

Canvas canvas = new Canvas(bitmap);

drawable.setBounds(0, 0, w, h);

drawable.draw(canvas);

return bitmap;

}

private Bitmap zoomDrawable(Drawable drawable) {

int width = drawable.getIntrinsicWidth();

int height = drawable.getIntrinsicHeight();

Bitmap oldbmp = drawableToBitamp(drawable);

Matrix matrix = new Matrix();

float scaleWidth = ((float) getWidth() / width);

float scaleHeight = ((float) getHeight() / height);

matrix.postScale(scaleWidth, scaleHeight);

Bitmap newbmp = Bitmap.createBitmap(oldbmp, 0, 0, width, height,

matrix, true);

return newbmp;

}

}

===========================上面为整个类===============================

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值