Android Draw the custom view as in google pay

前端 未结 2 466
感动是毒
感动是毒 2020-12-06 14:16

This question has already been asked and an answer has been accepted here but the accepted answer is not what I am looking for. I want to use a customview in which

相关标签:
2条回答
  • 2020-12-06 14:37

    You need to draw the curves using Cubic Bézier Curve. A good article to know how to draw such curves is written by Bartosz Ciechanowski, here.

    I have developed a View to draw a shape like google pay which inherits from FrameLayout. The source code is available on its github repository (but not documented yet!). However, add the following lines to your app level build.gradle file:

    repositories {
        jcenter()
    }
    
    dependencies {
        implementation 'com.aminography:beziercurvebulgelayout:1.0.2'
    }
    

    Then you can use it in xml layout files as following:

    <com.aminography.view.BezierCurveBulgeLayout
        android:id="@+id/bulgeLayout"
        android:layout_width="match_parent"
        android:layout_height="56dp"
        app:bulgeType="bulge"
        app:bulgeColor="@color/colorPrimary"
        app:curveWidth="32dp"
        app:flatWidth="56dp"
        app:flatHeight="24dp">
    
        <android.support.v7.widget.AppCompatImageView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center"
            android:src="@android:drawable/ic_menu_compass"/>
    
    </com.aminography.view.BezierCurveBulgeLayout>
    

    .

    Its shape and color is customizable to achieve the target shape by changing below attributes:

    0 讨论(0)
  • 2020-12-06 14:38

    In addition of above answer of @aminography

    If anyone looking for answer in java here is the working code in JAVA

    BezierCurveBulgeLayout

    import android.content.Context;
    import android.content.res.TypedArray;
    import android.graphics.*;
    import android.os.Build;
    import android.support.annotation.NonNull;
    import android.support.annotation.Nullable;
    import android.support.annotation.RequiresApi;
    import android.util.AttributeSet;
    import android.widget.FrameLayout;
    
    public class BezierCurveBulgeLayout extends FrameLayout {
    
        AttributeSet attrs;
        int defStyleAttr = 0;
        int defStyleRes = 0;
    
        private int curveWidth;
        private int flatWidth;
        private int flatHeight;
        private int bulgeColor;
        private BulgeType bulgeType;
    
    
        private Path path = new Path();
        private Paint paint = new Paint();
    
        private Point startCurveStartPoint = new Point();
        private Point startCurveEndPoint = new Point();
        private Point startCurveFirstControlPoint = new Point();
        private Point startCurveSecondControlPoint = new Point();
    
        private Point endCurveStartPoint = new Point();
        private Point endCurveEndPoint = new Point();
        private Point endCurveFirstControlPoint = new Point();
        private Point endCurveSecondControlPoint = new Point();
    
        public BezierCurveBulgeLayout(@NonNull Context context) {
            super(context);
            init();
        }
    
    
        public BezierCurveBulgeLayout(@NonNull Context context, @Nullable AttributeSet attrs) {
            super(context, attrs);
            this.attrs = attrs;
    
            init();
        }
    
        public BezierCurveBulgeLayout(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
            super(context, attrs, defStyleAttr);
            this.attrs = attrs;
            this.defStyleAttr = defStyleAttr;
            init();
        }
    
        @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
        public BezierCurveBulgeLayout(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
            super(context, attrs, defStyleAttr, defStyleRes);
            this.attrs = attrs;
            this.defStyleAttr = defStyleAttr;
            this.defStyleRes = defStyleRes;
            init();
        }
    
    
        private void init() {
    
            TypedArray a = getContext().obtainStyledAttributes(attrs, R.styleable.BezierCurveBulgeLayout, defStyleAttr, defStyleRes);
    
            curveWidth = a.getDimensionPixelSize(R.styleable.BezierCurveBulgeLayout_curveWidth, 0);
            flatWidth = a.getDimensionPixelSize(R.styleable.BezierCurveBulgeLayout_flatWidth, 0);
            flatHeight = a.getDimensionPixelSize(R.styleable.BezierCurveBulgeLayout_flatHeight, 0);
            bulgeType = BulgeType.values()[a.getInt(R.styleable.BezierCurveBulgeLayout_bulgeType, BulgeType.BULGE.ordinal())];
            bulgeColor = a.getColor(R.styleable.BezierCurveBulgeLayout_bulgeColor, Color.WHITE);
    
            a.recycle();
    
            paint.setStyle(Paint.Style.FILL_AND_STROKE);
            paint.setColor(bulgeColor);
            setBackgroundColor(Color.TRANSPARENT);
        }
    
        @Override
        protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
            super.onLayout(changed, left, top, right, bottom);
        }
    
        @Override
        protected void onSizeChanged(int w, int h, int oldw, int oldh) {
            super.onSizeChanged(w, h, oldw, oldh);
    
            int viewWidth = getWidth();
            int viewHeight = getHeight();
    
            int baseY = 0;
            int flatY = 0;
    
            if (bulgeType == BulgeType.BULGE) baseY = flatHeight;
            else flatY = flatHeight;
    
    
            startCurveStartPoint.set(viewWidth / 2 - flatWidth / 2 - curveWidth * 7 / 6, baseY);
            startCurveEndPoint.set(viewWidth / 2 - flatWidth / 2, flatY);
    
    
            endCurveStartPoint.set(viewWidth / 2 + flatWidth / 2, flatY);
            endCurveEndPoint.set(viewWidth / 2 + flatWidth / 2 + curveWidth * 7 / 6, baseY);
    
    
            startCurveFirstControlPoint.set(startCurveStartPoint.x + curveWidth * 5 / 8, startCurveStartPoint.y);
            startCurveSecondControlPoint.set(startCurveEndPoint.x - curveWidth / 2, startCurveEndPoint.y);
    
            endCurveFirstControlPoint.set(endCurveStartPoint.x + curveWidth / 2, endCurveStartPoint.y);
            endCurveSecondControlPoint.set(endCurveEndPoint.x - curveWidth * 5 / 8, endCurveEndPoint.y);
    
            path.reset();
            path.moveTo(0f, baseY);
            path.lineTo((float) startCurveStartPoint.x, (float) startCurveStartPoint.y);
    
            path.cubicTo(
                    (float) startCurveFirstControlPoint.x, (float) startCurveFirstControlPoint.y,
                    (float) startCurveSecondControlPoint.x, (float) startCurveSecondControlPoint.y,
                    (float) startCurveEndPoint.x, (float) startCurveEndPoint.y
            );
    
            path.lineTo((float) endCurveStartPoint.x, (float) endCurveStartPoint.y);
    
            path.cubicTo(
                    (float) endCurveFirstControlPoint.x, (float) endCurveFirstControlPoint.y,
                    (float) endCurveSecondControlPoint.x, (float) endCurveSecondControlPoint.y,
                    (float) endCurveEndPoint.x, (float) endCurveEndPoint.y
            );
    
            path.lineTo((float) viewWidth, (float) baseY);
            path.lineTo((float) viewWidth, (float) viewHeight);
            path.lineTo(0f, (float) viewHeight);
            path.close();
        }
    
        @Override
        protected void onDraw(Canvas canvas) {
            super.onDraw(canvas);
            canvas.drawPath(path, paint);
        }
    
        public enum BulgeType {
            BULGE,
            NOTCH
        }
    
    }
    

    attrs.xml

    <?xml version="1.0" encoding="utf-8"?>
    <resources>
        <declare-styleable name="BezierCurveBulgeLayout">
            <attr name="curveWidth" format="dimension"/>
            <attr name="flatWidth" format="dimension"/>
            <attr name="flatHeight" format="dimension"/>
            <attr name="bulgeColor" format="color"/>
            <attr name="bulgeType" format="enum">
                <enum name="bulge" value="0"/>
                <enum name="notch" value="1"/>
            </attr>
        </declare-styleable>
    </resources>
    

    Now use like this in your layout.xml file

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="#00fff7"
        android:gravity="center"
        tools:context=".MainActivity">
    
        <neel.com.demo.BezierCurveBulgeLayout
            android:id="@+id/bulgeLayout"
            android:layout_width="match_parent"
            android:layout_height="56dp"
            app:bulgeColor="@color/colorPrimary"
            app:bulgeType="bulge"
            app:curveWidth="32dp"
            app:flatHeight="20dp"
            app:flatWidth="80dp">
    
            <ImageView
                android:layout_width="50dp"
                android:layout_height="50dp"
                android:layout_gravity="center"
                android:src="@drawable/ic_fav" />
    
        </neel.com.demo.BezierCurveBulgeLayout>
    
    </LinearLayout>
    

    OUTPUT

    0 讨论(0)
提交回复
热议问题