Android 在 google pay 中绘制自定义视图

Posted

技术标签:

【中文标题】Android 在 google pay 中绘制自定义视图【英文标题】:Android Draw the custom view as in google pay 【发布时间】:2019-05-16 09:51:38 【问题描述】:

这个问题已经被问过并且答案已经被接受here 但接受的答案不是我想要的。我想使用一个自定义视图,其中槽口采用宽度+它正在遍历的视图的一些边距,如上图中的支付图标。在查看底部应用程序栏时,里面有一个像 this 这样的工厂 我看到了一个名为edge treatment class 的类,我想它也可以使用。我现在没有发布我的 customview 代码,因为我只能画一个矩形。

【问题讨论】:

【参考方案1】:

您需要使用Cubic Bézier Curve 绘制曲线。 Bartosz Ciechanowski 写了一篇了解如何绘制此类曲线的好文章,here。

我开发了一个View 来绘制类似于 google pay 的形状,它继承自 FrameLayout。源代码可在its github repository 上获得(但尚未记录!)。但是,将以下行添加到您的应用级别 build.gradle 文件中:

repositories 
    jcenter()


dependencies 
    implementation 'com.aminography:beziercurvebulgelayout:1.0.2'

然后你可以在xml布局文件中使用它,如下:

<com.aminography.view.BezierCurveBulgeLayout
    android:id="@+id/bulgeLayout"
    android:layout_
    android:layout_
    app:bulgeType="bulge"
    app:bulgeColor="@color/colorPrimary"
    app:curveWidth="32dp"
    app:flatWidth="56dp"
    app:flatHeight="24dp">

    <android.support.v7.widget.AppCompatImageView
        android:layout_
        android:layout_
        android:layout_gravity="center"
        android:src="@android:drawable/ic_menu_compass"/>

</com.aminography.view.BezierCurveBulgeLayout>

.

它的形状和颜色是可定制的,通过改变以下属性来实现目标形状:

【讨论】:

对不起@aminography 我错误地接受了另一个答案。请稍等一下,我有一个老问题,一旦我可以提高赏金,我会在那里给你你的代表。现在我似乎处于某种类型的冷却时间。顺便说一句,你做教程吗??? 嘿@aminography 您是否愿意在另一个问题上获得赏金,只需给出一个合理的答案***.com/questions/49584981/weakhandler-memory-leak【参考方案2】:

除了@aminography的上述答案

如果有人在这里寻找 java 中的答案是 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>

现在在你的 layout.xml 文件中像这样使用

<?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_
    android:layout_
    android:background="#00fff7"
    android:gravity="center"
    tools:context=".MainActivity">

    <neel.com.demo.BezierCurveBulgeLayout
        android:id="@+id/bulgeLayout"
        android:layout_
        android:layout_
        app:bulgeColor="@color/colorPrimary"
        app:bulgeType="bulge"
        app:curveWidth="32dp"
        app:flatHeight="20dp"
        app:flatWidth="80dp">

        <ImageView
            android:layout_
            android:layout_
            android:layout_gravity="center"
            android:src="@drawable/ic_fav" />

    </neel.com.demo.BezierCurveBulgeLayout>

</LinearLayout>

输出

【讨论】:

谢谢老兄 :) 我用 kotlin 写了这个库,可能有人在 java 中需要它。 @aminography 是的,谢谢,所有的功劳都归功于你;这就是为什么我添加了 In addition of above answer of @aminography 希望对其他人有所帮助

以上是关于Android 在 google pay 中绘制自定义视图的主要内容,如果未能解决你的问题,请参考以下文章

Android Chrome Webview 无法访问 Google Pay

Android 中的 Google Pay API 集成

试图将Google Pay集成到我的Android应用中

Google Pay UPI 集成在 Android 中不起作用

如何自定义 Google Pay 的付款单?

Google Pass 标签未显示在 iPhone 上的 Google Pay 应用中