美文网首页
自定义圆角矩形、圆形ImageView

自定义圆角矩形、圆形ImageView

作者: 失足者 | 来源:发表于2019-10-22 17:00 被阅读0次

首先在values下面创建attrs.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <declare-styleable name="FilletImageView">
        <attr name="shape_mode" format="enum">
            <enum name="round_rect" value="1"/>
            <enum name="circle" value="2"/>
        </attr>
        <attr name="round_radius" format="dimension"/>
    </declare-styleable>
</resources>

创建类FilletImageView继承AppCompatImageView。完整代码:

package com.example.baselibs.widget;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
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.os.Build;
import android.util.AttributeSet;

import androidx.appcompat.widget.AppCompatImageView;

import com.example.baselibs.R;

import java.util.Arrays;

/**
 *圆角加载图片控件
 */
public class FilletImageView extends AppCompatImageView {
    private static final int SHAPE_MODE_ROUND_RECT=1;
    private static final int SHAPE_MODE_CIRCLE=2;

    private int mShapeMode=0;//显示形状
    private int width,height;
    private float[] srcRadii=new float[8];
    private float mRadius=0;//半径
    private Paint mPaint;//画笔
    private RectF srcRectF;//图片占的矩形区域
    private Path mPath;//用来裁剪图片的path
    private Path srcPath;//图片区域大小的path
    private Xfermode xfermode;



    public FilletImageView(Context context) {
        super(context);
        init(null);
    }

    public FilletImageView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init(attrs);
    }

    public FilletImageView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init(attrs);
    }

    private void init(AttributeSet attrs){
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB){
            setLayerType(LAYER_TYPE_HARDWARE,null);
        }
        if (attrs!=null){
            TypedArray ta=getContext().obtainStyledAttributes(attrs, R.styleable.FilletImageView);
            mShapeMode=ta.getInt(R.styleable.FilletImageView_shape_mode,0);
            mRadius=ta.getDimension(R.styleable.FilletImageView_round_radius,0);
            ta.recycle();
        }
        srcRectF=new RectF();
        mPath=new Path();
        mPaint=new Paint();
        if (Build.VERSION.SDK_INT<=Build.VERSION_CODES.O_MR1){
            xfermode=new PorterDuffXfermode(PorterDuff.Mode.DST_IN);
        }else {
            xfermode=new PorterDuffXfermode(PorterDuff.Mode.DST_OUT);
            srcPath=new Path();
        }

    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        width=w;
        height=h;
    }

    @Override
    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
        super.onLayout(changed, left, top, right, bottom);
        if (changed){
            switch (mShapeMode){
                case SHAPE_MODE_ROUND_RECT://圆角矩形
                    srcRectF.set(0,0,width,height);
                    break;
                case SHAPE_MODE_CIRCLE://圆形
                    int min=Math.min(getWidth(),getHeight());
                    mRadius= min/2.0f;
                    srcRectF.set(width/2.0f-mRadius,height/2.0f-mRadius,
                            width/2.0f+mRadius,height/2.0f+mRadius);

                    break;
            }
            //填充四个角圆角的半径
            Arrays.fill(srcRadii,mRadius);
        }
    }


    @Override
    protected void onDraw(Canvas canvas) {
        // 使用图形混合模式来显示指定区域的图片
        canvas.saveLayer(srcRectF,null,Canvas.ALL_SAVE_FLAG);
        super.onDraw(canvas);
        //每次绘制前,重置画笔
        mPaint.reset();
        mPath.reset();
        switch (mShapeMode){
            case SHAPE_MODE_ROUND_RECT:
                mPath.addRoundRect(srcRectF,srcRadii,Path.Direction.CCW);
                break;
            case SHAPE_MODE_CIRCLE:
                mPath.addCircle(width/2.0f,height/2.0f,mRadius,Path.Direction.CCW);
                break;
        }
        //这里要注意,前面重置画笔了,要在这里从新设置
        mPaint.setAntiAlias(true);
        mPaint.setStyle(Paint.Style.FILL);
        mPaint.setXfermode(xfermode);
        if (Build.VERSION.SDK_INT<=Build.VERSION_CODES.O_MR1){
            canvas.drawPath(mPath,mPaint);
        }else {
            srcPath.addRect(srcRectF,Path.Direction.CCW);
            // 计算tempPath和path的差集
            srcPath.op(mPath,Path.Op.DIFFERENCE);
            canvas.drawPath(srcPath,mPaint);
        }
        mPaint.setXfermode(null);
        //恢复画布状态
        canvas.restore();
    }
}

在布局中使用:只需要设置mode和radius两个参数。而且必须两个都要设置才有效果

<com.example.baselibs.widget.FilletImageView
        android:id="@+id/iv_app_icon"
        android:layout_width="100dp"
        android:layout_height="100dp"
        app:shape_mode="round_rect"
        app:round_radius="30dp"
        android:src="@mipmap/em_default_avatar"
        tools:ignore="MissingConstraints"/>

相关文章

网友评论

      本文标题:自定义圆角矩形、圆形ImageView

      本文链接:https://www.haomeiwen.com/subject/bjzqvctx.html