想要用曲线做图像侧圆角想要删除图像中出现的线

时间:2018-03-08 07:44:07

标签: android android-layout canvas paint

我正在使用曲线裁剪图像侧圆角想要删除图像中出现的线条,如您在帖子中提到的输出屏幕中所示

使用quadTo裁剪圆弧形状,然后应用arcTo使角落变圆(平滑),如参考图像中所述

参考图片

enter image description here

ArcLayout.java

 import android.content.Context;
    import android.graphics.Canvas;
    import android.graphics.Color;
    import android.graphics.Outline;
    import android.graphics.Paint;
    import android.graphics.Path;
    import android.graphics.PorterDuff;
    import android.graphics.PorterDuffXfermode;
    import android.graphics.RectF;
    import android.os.Build;
    import android.support.annotation.RequiresApi;
    import android.support.v4.view.ViewCompat;
    import android.util.AttributeSet;
    import android.view.View;
    import android.view.ViewOutlineProvider;
    import android.widget.FrameLayout;

    public class ArcLayout extends FrameLayout {

        private ArcLayoutSettings settings;

        private int height = 0;

        private int width = 0;

        private Path clipPathOne;

        private Path clipPathOneCurv;

        private Path clipPathTwoCurv;

        private float radius = 0, margin = 0;

        private final RectF cornerRect = new RectF();


        public ArcLayout(Context context) {
            super(context);
            init(context, null);
        }

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

        public void init(Context context, AttributeSet attrs) {
            settings = new ArcLayoutSettings(context, attrs);
            settings.setElevation(ViewCompat.getElevation(this));
            radius = settings.getRadius();
            margin = settings.getMargin();

            /**
             * If hardware acceleration is on (default from API 14), clipPathOne worked correctly
             * from API 18.
             *
             * So we will disable hardware Acceleration if API < 18
             *
             * https://developer.android.com/guide/topics/graphics/hardware-accel.html#unsupported
             * Section #Unsupported Drawing Operations
             */
            if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR2) {
                setLayerType(View.LAYER_TYPE_SOFTWARE, null);
            }
        }

        private Path createClipPath(int position) {
            final Path path = new Path();

            float arcHeight = settings.getArcHeight();

            switch (position) {
                case ArcLayoutSettings.POSITION_BOTTOM_CURVE:
                    if (settings.isCropInside()) {
                        path.moveTo(0, 0);
                        path.lineTo(0, height);
                        path.quadTo(width / 2, height - 2 * arcHeight, width, height);
                        path.lineTo(width, 0);
                        path.close();
                    } else {
                        path.moveTo(0, 0);
                        path.lineTo(0, height - arcHeight);
                        path.quadTo(width / 2, height + arcHeight, width, height - arcHeight);
                        path.lineTo(width, 0);
                        path.close();
                    }
                    break;

                case ArcLayoutSettings.POSITION_TOP_CURVE:
                    if (settings.isCropInside()) {
                        path.moveTo(0, height);
                        path.lineTo(0, 0);
                        path.quadTo(width / 2, 2 * arcHeight, width, 0);
                        path.lineTo(width, height);
                        path.close();
                    } else {
                        path.moveTo(0, arcHeight);
                        path.quadTo(width / 2, -arcHeight, width, arcHeight);
                        path.lineTo(width, height);
                        path.lineTo(0, height);
                        path.close();
                    }
                    break;


                case ArcLayoutSettings.POSITION_LEFT_CURVE:
                    if (settings.isCropInside()) {
                        path.moveTo(width, 0);
                        path.lineTo(0, 0);
                        path.quadTo(arcHeight * 2, height / 2, 0, height);
                        path.lineTo(width, height);
                        path.close();
                    } else {
                        path.moveTo(width, 0);
                        path.lineTo(arcHeight, 0);
                        path.quadTo(-arcHeight, height / 2, arcHeight, height);
                        path.lineTo(width, height);
                        path.close();
                    }
                    break;
                case ArcLayoutSettings.POSITION_RIGHT_CURVE:
                    if (settings.isCropInside()) {
                        path.moveTo(0, 0);
                        path.lineTo(width, 0);
                        path.quadTo(width - arcHeight * 2, height / 2, width, height);
                        path.lineTo(0, height);
                        path.close();
                    } else {
                        path.moveTo(0, 0);
                        path.lineTo(width - arcHeight, 0);
                        path.quadTo(width + arcHeight, height / 2, width - arcHeight, height);
                        path.lineTo(0, height);
                        path.close();
                    }
                    break;

            }

            return path;
        }


        @Override
        protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
            super.onLayout(changed, left, top, right, bottom);
            if (changed) {
                calculateLayout();
            }
        }

        private void calculateLayout() {
            if (settings == null) {
                return;
            }
            height = getMeasuredHeight();
            width = getMeasuredWidth();

            if (radius > 0 && settings.getRounded_corn_pos() != ArcLayoutSettings.POSITION_DEFAULT) {
                clipPathOne = roundedCornerPath(radius, settings.getRounded_corn_pos());
            }

            if (settings.getArc_position() != ArcLayoutSettings.POSITION_DEFAULT) {


                if (width > 0 && height > 0) {
                    if (settings.getArc_position() == ArcLayoutSettings.POSITION_BOTH_CURVE) {
                        clipPathOneCurv = createClipPath(ArcLayoutSettings.POSITION_TOP_CURVE);
                        clipPathTwoCurv = createClipPath(ArcLayoutSettings.POSITION_BOTTOM_CURVE);
                    } else {
                        clipPathOneCurv = createClipPath(settings.getArc_position());
                    }

                    ViewCompat.setElevation(this, settings.getElevation());
                    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP && !settings.isCropInside()) {
                        ViewCompat.setElevation(this, settings.getElevation());
                        setOutlineProvider(new ViewOutlineProvider() {
                            @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
                            @Override
                            public void getOutline(View view, Outline outline) {
                                if (settings.getArc_position() == ArcLayoutSettings.POSITION_BOTH_CURVE) {
                                    outline.setConvexPath(clipPathOneCurv);
                                    outline.setConvexPath(clipPathTwoCurv);
                                } else {
                                    //outline.setConvexPath(clipPathOneCurv);
                                }
                            }
                        });
                    }
                }

            }
        }


        @Override
        protected void dispatchDraw(Canvas canvas) {
            Paint paint = new Paint();
            paint.setAntiAlias(true);
            paint.setColor(Color.WHITE);

            int saveCount = canvas.saveLayer(0, 0, getWidth(), getHeight(), null, Canvas.ALL_SAVE_FLAG);
            super.dispatchDraw(canvas);
            paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.MULTIPLY));

            if (clipPathOneCurv != null) {
                canvas.drawPath(clipPathOneCurv, paint);
            }
            if (clipPathTwoCurv != null) {
                canvas.drawPath(clipPathTwoCurv, paint);
            }
            if (clipPathOne != null) {
                canvas.drawPath(clipPathOne, paint);
            }


            canvas.restoreToCount(saveCount);


        }


        private Path roundedCornerPath(float cornerRadius, int position) {
            //path.rewind();
            Path path = new Path();
            final int width = getWidth();
            final int height = getHeight();
            final float twoRadius = cornerRadius * 2;
            cornerRect.set(-cornerRadius, -cornerRadius, cornerRadius, cornerRadius);

            if (position == ArcLayoutSettings.POSITION_TOP_LEFT_ROUND || position == ArcLayoutSettings.POSITION_TOP_ROUND || position == ArcLayoutSettings.POSITION_ALL_ROUND) {
                cornerRect.offsetTo(0f, settings.getArcHeight());
                path.arcTo(cornerRect, 180f, 90f);
            } else {
                path.moveTo(0f, 0f);
            }

            if (position == ArcLayoutSettings.POSITION_TOP_RIGHT_ROUND || position == ArcLayoutSettings.POSITION_TOP_ROUND || position == ArcLayoutSettings.POSITION_ALL_ROUND) {
                cornerRect.offsetTo(width - twoRadius, settings.getArcHeight());
                path.arcTo(cornerRect, 270f, 90f);
            } else {
                path.lineTo(width, 0f);
            }

            if (position == ArcLayoutSettings.POSITION_BOTTOM_RIGHT_ROUND || position == ArcLayoutSettings.POSITION_BOTTOM_ROUND || position == ArcLayoutSettings.POSITION_ALL_ROUND) {
                cornerRect.offsetTo(width - twoRadius, height - twoRadius);
                path.arcTo(cornerRect, 0f, 90f);
            } else {
                path.lineTo(width, height);
            }

            if (position == ArcLayoutSettings.POSITION_BOTTOM_LEFT_ROUND || position == ArcLayoutSettings.POSITION_BOTTOM_ROUND || position == ArcLayoutSettings.POSITION_ALL_ROUND) {
                cornerRect.offsetTo(0f, height - twoRadius);
                path.arcTo(cornerRect, 90f, 90f);
            } else {
                path.lineTo(0f, height);
            }

            path.close();
            return path;
        }

    }

rounded_drawable.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_centerInParent="true"
    android:background="@color/colorPrimaryDark"
    android:gravity="center">


        <com.example.sonalsb.curved_img.ArcLayout
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            app:arc_cropDirection="cropOutside"
            app:corner_position="top"
            app:corner_radius="12dp"
            app:arc_position="top"
            app:arc_height="8dp">


            <ImageView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_gravity="center_horizontal|bottom"
                android:adjustViewBounds="true"
                android:src="@drawable/cartoon" />

        </com.example.sonalsb.curved_img.ArcLayout>


</RelativeLayout>

attrs.xml

 <?xml version="1.0" encoding="utf-8"?>
    <resources>
        <declare-styleable name="ArcLayout">

            <attr name="arc_height" format="dimension" />

            <attr name="corner_radius" format="dimension"/>

            <attr name="corner_margin" format="dimension"/>

            <attr name="corner_position">
                <enum name="top_left" value="0"/>
                <enum name="top_right" value="1"/>
                <enum name="bottom_left" value="2"/>
                <enum name="bottom_right" value="3"/>

                <enum name="top" value="4"/>
                <enum name="bottom" value="5"/>
                <enum name="left" value="6"/>
                <enum name="right" value="7"/>

                <enum name="empty" value="9"/>
                <enum name="all" value="10"/>
            </attr>

            <attr name="arc_position">
                <enum name="bottom" value="0"/>
                <enum name="top" value="1"/>
                <enum name="left" value="2"/>
                <enum name="right" value="3"/>
                <enum name="both" value="4"/>

                <enum name="empty" value="99"/>
            </attr>
            <attr name="arc_cropDirection" format="enum">
                <enum name="cropInside" value="0" />
                <enum name="cropOutside" value="1"/>
            </attr>
        </declare-styleable>
    </resources>

输出

enter image description here

0 个答案:

没有答案