美文网首页
自定义圆角矩形、圆形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