Android 圆角ImageView实现
2021-11-17 本文已影响0人
小仙女喂得猪呀
由于项目之前的CircleImageView的实现方式是针对bitmap去操作的,不是很优雅,且在用glide加载gif的时候会偶现一个bitmap的转换异常,所以借此机会尽可能优雅的实现了一个专用的圆角ImageView,分享给各位大佬们,如有不当之处,请多多指点
for kotlin
class CircleImageView @JvmOverloads constructor(
context: Context, attrs: AttributeSet? = null
) : AppCompatImageView(context, attrs) {
private var mRadius: Int = 0
private val viewOutlineProvider: ViewOutlineProvider by lazy {
@RequiresApi(Build.VERSION_CODES.LOLLIPOP)
object : ViewOutlineProvider() {
override fun getOutline(view: View?, outline: Outline?) {
val width = width
val height = height
outline?.setRoundRect(0, 0, width, height, mRadius.toFloat())
}
}
}
private var path: Path?
private var rect: RectF?
init {
val obtainStyledAttributes =
context.obtainStyledAttributes(attrs, R.styleable.CircleImageViewV3)
obtainStyledAttributes.let {
mRadius =
it.getInt(
R.styleable.CircleImageViewV3_CustomizeRadiusV3,
(getContext().resources.getDimension(R.dimen.dp_10)).toInt()
)
it.recycle()
path = Path()
rect = RectF()
if (ModuleUtils.isRoundCornerMask()) { //只对小度做圆角处理
setRound(mRadius)
}
}
}
//设置圆角图片
fun setRound(radius: Int) = apply {
val isChange = radius != mRadius
mRadius = radius
if (mRadius != 0) {
if (Build.VERSION_CODES.LOLLIPOP <= Build.VERSION.SDK_INT) {
outlineProvider = viewOutlineProvider
clipToOutline = true
}
val width = width.toFloat()
val height = height.toFloat()
rect?.set(0f, 0f, width, height)
path?.reset()
rect?.let { path?.addRoundRect(it,mRadius.toFloat(),mRadius.toFloat(),Path.Direction.CW) }
} else {
if (Build.VERSION_CODES.LOLLIPOP <= Build.VERSION.SDK_INT) {
clipToOutline = false
}
}
if (isChange) {
if (Build.VERSION_CODES.LOLLIPOP <= Build.VERSION.SDK_INT) {
invalidateOutline()
}
}
}
override fun draw(canvas: Canvas?){
var clip = false
if (Build.VERSION_CODES.LOLLIPOP > Build.VERSION.SDK_INT && mRadius > 0) {
clip = true
canvas?.save()
path?.let { canvas?.clipPath(it) }
}
super.draw(canvas)
if (clip) {
canvas?.restore()
}
}
}
for java
package com.wj.motiondemo;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Outline;
import android.graphics.Path;
import android.graphics.RectF;
import android.os.Build;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewOutlineProvider;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.widget.AppCompatImageView;
/**
* @Author : jiyajie
* @Time : On 2021/11/23 09:45
* @Description : CircleImageViewV2
*/
public class CircleImageViewV2 extends AppCompatImageView {
private int mRadius;
private Path mPath;
private RectF mRectF;
private ViewOutlineProvider viewOutlineProvider;
public CircleImageViewV2(@NonNull Context context) {
this(context, null);
}
public CircleImageViewV2(@NonNull Context context, @Nullable AttributeSet attrs) {
this(context, attrs, 0);
}
public CircleImageViewV2(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(context, attrs);
}
private void init(Context context, AttributeSet attrs) {
TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.CircleImageViewV2);
mRadius = (int) typedArray.getDimension(R.styleable.CircleImageViewV2_CustomizeRadiusV2, 0f);
typedArray.recycle();
setmRadius(mRadius);
}
//更新图片圆角
public void setmRadius(int radius) {
boolean isChange = radius != mRadius;
mRadius = radius;
if (mPath == null) {
mPath = new Path();
}
if (mRectF == null) {
mRectF = new RectF();
}
if (mRadius != 0) {
if (Build.VERSION_CODES.LOLLIPOP <= Build.VERSION.SDK_INT) {
if (viewOutlineProvider == null) {
viewOutlineProvider = new ViewOutlineProvider() {
@Override
public void getOutline(View view, Outline outline) {
int width = getWidth();
int height = getHeight();
outline.setRoundRect(0,0,width,height,mRadius);
}
};
}
setOutlineProvider(viewOutlineProvider);
setClipToOutline(true);
}
mRectF.set(0, 0, getWidth(), getHeight());
mPath.reset();
mPath.addRoundRect(mRectF, mRadius, mRadius, Path.Direction.CW);
} else {
if (Build.VERSION_CODES.LOLLIPOP <= Build.VERSION.SDK_INT) {
setClipToOutline(false);
}
}
if (isChange) {
if (Build.VERSION_CODES.LOLLIPOP <= Build.VERSION.SDK_INT) {
invalidateOutline();
}
}
}
@Override
public void draw(Canvas canvas) {
boolean clip = false;
if (Build.VERSION_CODES.LOLLIPOP > Build.VERSION.SDK_INT && mRadius > 0) {
clip = true;
canvas.save();
canvas.clipPath(mPath);
}
super.draw(canvas);
if (clip) {
canvas.restore();
}
}
}
效果如图:
WechatIMG8222.png