天天看点

圆角矩形圆形图片简单解决方案

一个圆角图片的解决方案,解决设计需要不同圆角图片时,避免重复让设计师出不一样的切图。

废话不多说,先上效果图:

圆角矩形圆形图片简单解决方案
属性介绍
参数 属性 介绍
round_rect_circle boolean 是否显示圆形
round_rect_corner int 圆角大小
round_rect_corner_top_to_left int 左上角圆弧
round_rect_corner_top_to_right int 右上角圆弧
round_rect_corner_bottom_to_left int 左下角圆弧
round_rect_corner_bottom_to_right int 右下角圆弧
round_rect_stroke_color int 描边颜色
round_rect_stroke_width int 描边大小

* round_rect_circle:默认false,如果是true,直接绘制圆形。

* round_rect_corner:四个角圆弧属性,默认为0。

* round_rect_corner_top_to_left:左上角圆弧,如果设置了该属性,round_rect_corner的左上角设置不起作用。

* round_rect_corner_top_to_right:右上角圆弧,如果设置了该属性,round_rect_corner的右上角设置不起作用。

* round_rect_corner_bottom_to_left:左下角圆弧,如果设置了该属性,round_rect_corner的左下角设置不起作用。

* round_rect_corner_bottom_to_right:右下角圆弧,如果设置了该属性,round_rect_corner的右下角设置不起作用。

* round_rect_stroke_color:描边的颜色,默认是白色。

* round_rect_stroke_width:圆弧的描边,默认描边的宽度是0。

实现思路

先上完整代码:

首先先定义圆角图形所需要的属性:

<declare-styleable name="RoundRectLayout">
        <attr name="round_rect_circle" format="boolean"/>
        <attr name="round_rect_corner" format="dimension"/>
        <attr name="round_rect_corner_top_to_left" format="dimension"/>
        <attr name="round_rect_corner_top_to_right" format="dimension"/>
        <attr name="round_rect_corner_bottom_to_left" format="dimension"/>
        <attr name="round_rect_corner_bottom_to_right" format="dimension"/>
        <attr name="round_rect_stroke_color" format="color"/>
        <attr name="round_rect_stroke_width" format="dimension"/>
    </declare-styleable>
           

然后在定义一个RoundRectLayout继承RelativeLayout:完整代码如下:

ublic class RoundRectLayout extends RelativeLayout {

    private RectF mRectF;//绘制画布的大小
    public float[] mRadii = new float[];//绘制眼角矩形所需的8个角
    private boolean mCircle;//是否是绘制圆形
    private int mRectCorner; //圆角弧度
    private int mStrokeColor;// 描边颜色
    private int mStrokeWidth;// 描边宽度

    public RoundRectLayout(Context context) {
        this(context, null);
    }

    public RoundRectLayout(Context context, AttributeSet attrs) {
        this(context, attrs, );
    }

    public RoundRectLayout(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        initView(context, attrs);
    }

    private void initView(Context context, AttributeSet attrs) {
        TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.RoundRectLayout);
        mCircle = array.getBoolean(R.styleable.RoundRectLayout_round_rect_circle, false);
        mRectCorner = array.getDimensionPixelSize(R.styleable.RoundRectLayout_round_rect_corner, );
        int roundRectTopLeft = array.getDimensionPixelSize(R.styleable.RoundRectLayout_round_rect_corner_top_to_left, -);
        int roundRectTopRight = array.getDimensionPixelSize(R.styleable.RoundRectLayout_round_rect_corner_top_to_right, -);
        int roundRectBottomLeft = array.getDimensionPixelSize(R.styleable.RoundRectLayout_round_rect_corner_bottom_to_left, -);
        int roundRectBottomRight = array.getDimensionPixelSize(R.styleable.RoundRectLayout_round_rect_corner_bottom_to_right, -);

        mRadii[] = roundRectTopLeft == - ? mRectCorner : roundRectTopLeft;
        mRadii[] = roundRectTopLeft == - ? mRectCorner : roundRectTopLeft;
        mRadii[] = roundRectTopRight == - ? mRectCorner : roundRectTopRight;
        mRadii[] = roundRectTopRight == - ? mRectCorner : roundRectTopRight;
        mRadii[] = roundRectBottomLeft == - ? mRectCorner : roundRectBottomLeft;
        mRadii[] = roundRectBottomLeft == - ? mRectCorner : roundRectBottomLeft;
        mRadii[] = roundRectBottomRight == - ? mRectCorner : roundRectBottomRight;
        mRadii[] = roundRectBottomRight == - ? mRectCorner : roundRectBottomRight;

        mStrokeColor = array.getColor(R.styleable.RoundRectLayout_round_rect_stroke_color, Color.WHITE);
        mStrokeWidth = array.getDimensionPixelSize(R.styleable.RoundRectLayout_round_rect_stroke_width, );
        array.recycle();

        mRectF = new RectF();
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        mRectF.left = getPaddingLeft();
        mRectF.top = getPaddingTop();
        mRectF.right = w - getPaddingRight();
        mRectF.bottom = h - getPaddingBottom();
    }

    @Override
    protected void dispatchDraw(Canvas canvas) {
        canvas.saveLayer(mRectF, null, Canvas.ALL_SAVE_FLAG);
        super.dispatchDraw(canvas);
        Path path = new Path();
        path.reset();
        //判断是否绘制圆
        if (mCircle) {
            float width = (mRectF.right - mRectF.left) > (mRectF.bottom - mRectF.top) ? mRectF.bottom - mRectF.top : mRectF.right - mRectF.left;
            path.addCircle((mRectF.right - mRectF.left) / , (mRectF.bottom - mRectF.top) / , (width - mStrokeWidth) / , Path.Direction.CW);
        } else {
            path.addRoundRect(mRectF, mRadii, Path.Direction.CW);
        }


        Paint paint = new Paint();
        paint.setAntiAlias(true);

        //绘制描边
        if (mStrokeWidth > ) {
            paint.setColor(mStrokeColor);
            paint.setStrokeWidth(mStrokeWidth);
            paint.setStyle(Paint.Style.STROKE);
            canvas.drawPath(path, paint);
        }

        //剪切圆角矩形
        paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_IN));
        paint.setStyle(Paint.Style.FILL);
        canvas.drawPath(path, paint);
    }
}
           

使用步骤

在xml文件直接引用

<com.android.round.weight.RoundRectLayout
                    android:layout_width="100dp"
                    android:layout_height="100dp"
                    android:layout_margin="30dp"
                    app:round_rect_circle="true">

                    <ImageView
                        android:layout_width="match_parent"
                        android:layout_height="match_parent"
                        android:scaleType="centerCrop"
                        android:src="@mipmap/club_bg"/>

                    <TextView
                        android:layout_width="match_parent"
                        android:layout_height="40dp"
                        android:layout_alignParentBottom="true"
                        android:background="@mipmap/bottom_bg"
                        android:gravity="center"
                        android:textColor="@android:color/white"
                        android:textSize="10sp"/>

                </com.android.round.weight.RoundRectLayout>
           

具体的实现思路:

首先要获取自定义的属性:

TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.RoundRectLayout);
        mCircle = array.getBoolean(R.styleable.RoundRectLayout_round_rect_circle, false);
        mRectCorner = array.getDimensionPixelSize(R.styleable.RoundRectLayout_round_rect_corner, );
        int roundRectTopLeft = array.getDimensionPixelSize(R.styleable.RoundRectLayout_round_rect_corner_top_to_left, -);
        int roundRectTopRight = array.getDimensionPixelSize(R.styleable.RoundRectLayout_round_rect_corner_top_to_right, -);
        int roundRectBottomLeft = array.getDimensionPixelSize(R.styleable.RoundRectLayout_round_rect_corner_bottom_to_left, -);
        int roundRectBottomRight = array.getDimensionPixelSize(R.styleable.RoundRectLayout_round_rect_corner_bottom_to_right, -);

        mRadii[] = roundRectTopLeft == - ? mRectCorner : roundRectTopLeft;
        mRadii[] = roundRectTopLeft == - ? mRectCorner : roundRectTopLeft;
        mRadii[] = roundRectTopRight == - ? mRectCorner : roundRectTopRight;
        mRadii[] = roundRectTopRight == - ? mRectCorner : roundRectTopRight;
        mRadii[] = roundRectBottomLeft == - ? mRectCorner : roundRectBottomLeft;
        mRadii[] = roundRectBottomLeft == - ? mRectCorner : roundRectBottomLeft;
        mRadii[] = roundRectBottomRight == - ? mRectCorner : roundRectBottomRight;
        mRadii[] = roundRectBottomRight == - ? mRectCorner : roundRectBottomRight;

        mStrokeColor = array.getColor(R.styleable.RoundRectLayout_round_rect_stroke_color, Color.WHITE);
        mStrokeWidth = array.getDimensionPixelSize(R.styleable.RoundRectLayout_round_rect_stroke_width, );
        array.recycle();
           

获取到之后要及时关闭typeArray,这个不需要详述,然后在onSizeChanged()方法中获取当前view的大小属性。onSizeChanged方法会在view有改动的时候调用,第一次创建view的时候也会调用一次。然后在dispatchDraw()方法中绘制图形。

因为要使用setXfermode方法,所以首先要进行离屏缓冲,至于为什么,请点击了解,行离屏缓冲很简单,只需要一行代码:

然后判断是绘制圆形还是圆角矩形,绘制画布路径

Path path = new Path();
        path.reset();
        //判断是否绘制圆
        if (mCircle) {
            float width = (mRectF.right - mRectF.left) > (mRectF.bottom - mRectF.top) ? mRectF.bottom - mRectF.top : mRectF.right - mRectF.left;
            path.addCircle((mRectF.right - mRectF.left) / , (mRectF.bottom - mRectF.top) / , (width - mStrokeWidth) / , Path.Direction.CW);
        } else {
            path.addRoundRect(mRectF, mRadii, Path.Direction.CW);
        }
           

之后判断是否需要描边

//绘制描边
        if (mStrokeWidth > ) {
            paint.setColor(mStrokeColor);
            paint.setStrokeWidth(mStrokeWidth);
            paint.setStyle(Paint.Style.STROKE);
            canvas.drawPath(path, paint);
        }
           

最后通过drawPath方法绘制需要的图形

//剪切圆角矩形
        paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_IN));
        paint.setStyle(Paint.Style.FILL);
        canvas.drawPath(path, paint);
           

代码很简单,如果有需要,可以直接引用git项目

PS:有问题可以加v1054353861,共同学习,提高!