Android仿支付宝订单确认和支付

来源:互联网 发布:windows 7 beta 编辑:程序博客网 时间:2024/06/04 18:49

1.效果图


2.实现方式

dialog_confirm_order.xml

<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:orientation="vertical"    android:layout_width="match_parent"    android:layout_height="match_parent"    android:background="#ffffff">    <LinearLayout        android:paddingLeft="10dp"        android:paddingRight="10dp"        android:orientation="horizontal"        android:layout_width="match_parent"        android:layout_height="40dp">        <TextView            android:textColor="#000000"            android:layout_weight="1"            android:layout_gravity="center_vertical"            android:text="在线支付"            android:layout_width="wrap_content"            android:layout_height="wrap_content" />        <TextView            android:id="@+id/tv_close"            android:textColor="#000000"            android:text="X"            android:layout_gravity="center_vertical"            android:layout_width="wrap_content"            android:layout_height="wrap_content" />    </LinearLayout>    <LinearLayout        android:paddingLeft="10dp"        android:paddingRight="10dp"        android:orientation="horizontal"        android:layout_width="match_parent"        android:layout_height="30dp">        <TextView            android:layout_weight="1"            android:layout_gravity="center_vertical"            android:text="支付金额"            android:layout_width="wrap_content"            android:layout_height="wrap_content" />        <TextView            android:text="¥50.00"            android:layout_gravity="center_vertical"            android:layout_width="wrap_content"            android:layout_height="wrap_content" />    </LinearLayout>    <LinearLayout        android:paddingLeft="10dp"        android:paddingRight="10dp"        android:orientation="horizontal"        android:layout_width="match_parent"        android:layout_height="30dp">        <TextView            android:layout_weight="1"            android:layout_gravity="center_vertical"            android:text="订单信息"            android:layout_width="wrap_content"            android:layout_height="wrap_content" />        <TextView            android:text="某某某购买了十桶泡面"            android:layout_gravity="center_vertical"            android:layout_width="wrap_content"            android:layout_height="wrap_content" />    </LinearLayout>    <LinearLayout        android:paddingLeft="10dp"        android:paddingRight="10dp"        android:orientation="horizontal"        android:layout_width="match_parent"        android:layout_height="30dp">        <TextView            android:layout_weight="1"            android:layout_gravity="center_vertical"            android:text="付款方式"            android:layout_width="wrap_content"            android:layout_height="wrap_content" />        <TextView            android:text="账户余额"            android:layout_gravity="center_vertical"            android:layout_width="wrap_content"            android:layout_height="wrap_content" />    </LinearLayout>    <TextView        android:layout_gravity="center_vertical"        android:layout_width="match_parent"        android:layout_height="40dp" />    <Button        android:id="@+id/btn_confirmorder"        android:background="#9bbdf2"        android:text="立即支付"        android:layout_width="match_parent"        android:layout_height="wrap_content" /></LinearLayout>

3.dialog_input_password.xml

<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:orientation="vertical"    android:layout_width="match_parent"    android:layout_height="match_parent"    android:background="#ffffff">    <LinearLayout        android:paddingLeft="10dp"        android:paddingRight="10dp"        android:orientation="horizontal"        android:layout_width="match_parent"        android:layout_height="40dp">        <TextView            android:id="@+id/tv_close"            android:text="X"            android:layout_gravity="center_vertical"            android:layout_width="wrap_content"            android:layout_height="wrap_content" />        <TextView            android:layout_marginLeft="10dp"            android:layout_weight="1"            android:layout_gravity="center_vertical"            android:text="请输入支付密码"            android:layout_width="wrap_content"            android:layout_height="wrap_content" />    </LinearLayout>    <LinearLayout        android:paddingLeft="40dp"        android:paddingRight="40dp"        android:orientation="horizontal"        android:layout_width="match_parent"        android:layout_height="wrap_content">        <com.example.mama.paydemo.widget.PayPsdInputView            android:inputType="number"            android:id="@+id/et_password"            android:layout_weight="1"            android:layout_width="wrap_content"            android:layout_height="wrap_content"            />    </LinearLayout>    <LinearLayout        android:orientation="vertical"        android:layout_width="match_parent"        android:layout_height="wrap_content">        <TextView            android:layout_gravity="right"            android:paddingTop="5dp"            android:paddingBottom="5dp"            android:paddingRight="40dp"            android:gravity="right"            android:text="忘记密码?"            android:layout_width="wrap_content"            android:layout_height="wrap_content" />    </LinearLayout></LinearLayout>

4.自定义输入框PayPsdInputView.java

package com.example.mama.paydemo.widget;import android.content.Context;import android.content.res.TypedArray;import android.graphics.Canvas;import android.graphics.Color;import android.graphics.Paint;import android.graphics.RectF;import android.text.InputFilter;import android.util.AttributeSet;import android.widget.EditText;import com.example.mama.paydemo.R;import static android.graphics.Paint.ANTI_ALIAS_FLAG;/** * Created by mama on 2017/12/5. */public class PayPsdInputView extends EditText {    private Context mContext;    /**     * 第一个圆开始绘制的圆心坐标     */    private float startX;    private float startY;    private float cX;    /**     * 实心圆的半径     */    private int radius = 10;    /**     * view的高度     */    private int height;    private int width;    /**     * 当前输入密码位数     */    private int textLength = 0;    private int bottomLineLength;    /**     * 最大输入位数     */    private int maxCount = 6;    /**     * 圆的颜色   默认BLACK     */    private int circleColor = Color.BLACK;    /**     * 底部线的颜色   默认GRAY     */    private int bottomLineColor = Color.GRAY;    /**     * 分割线的颜色     */    private int borderColor = Color.GRAY;    /**     * 分割线的画笔     */    private Paint borderPaint;    /**     * 分割线开始的坐标x     */    private int divideLineWStartX;    /**     * 分割线的宽度  默认2     */    private int divideLineWidth = 2;    /**     * 竖直分割线的颜色     */    private int divideLineColor = Color.GRAY;    private int focusedColor = Color.RED;    private RectF rectF = new RectF();    private RectF focusedRecF = new RectF();    private int psdType = 0;    private final static int psdType_weChat = 0;    private final static int psdType_bottomLine = 1;    /**     * 矩形边框的圆角     */    private int rectAngle = 0;    /**     * 竖直分割线的画笔     */    private Paint divideLinePaint;    /**     * 圆的画笔     */    private Paint circlePaint;    /**     * 底部线的画笔     */    private Paint bottomLinePaint;    /**     * 当前输入的位置索引     */    private int position = 0;    private onPasswordListener mListener;    public PayPsdInputView(Context context, AttributeSet attrs) {        super(context, attrs);        mContext = context;        getAtt(attrs);        initPaint();        this.setBackgroundColor(Color.TRANSPARENT);        this.setCursorVisible(false);        this.setFilters(new InputFilter[]{new InputFilter.LengthFilter(maxCount)});    }    private void getAtt(AttributeSet attrs) {        TypedArray typedArray = mContext.obtainStyledAttributes(attrs, R.styleable.PayPsdInputView);        maxCount = typedArray.getInt(R.styleable.PayPsdInputView_maxCount, maxCount);        circleColor = typedArray.getColor(R.styleable.PayPsdInputView_circleColor, circleColor);        bottomLineColor = typedArray.getColor(R.styleable.PayPsdInputView_bottomLineColor, bottomLineColor);        radius = typedArray.getDimensionPixelOffset(R.styleable.PayPsdInputView_radius, radius);        divideLineWidth = typedArray.getDimensionPixelSize(R.styleable.PayPsdInputView_divideLineWidth, divideLineWidth);        divideLineColor = typedArray.getColor(R.styleable.PayPsdInputView_divideLineColor, divideLineColor);        psdType = typedArray.getInt(R.styleable.PayPsdInputView_psdType, psdType);        rectAngle = typedArray.getDimensionPixelOffset(R.styleable.PayPsdInputView_rectAngle, rectAngle);        focusedColor = typedArray.getColor(R.styleable.PayPsdInputView_focusedColor, focusedColor);        typedArray.recycle();    }    /**     * 初始化画笔     */    private void initPaint() {        circlePaint = getPaint(5, Paint.Style.FILL, circleColor);        bottomLinePaint = getPaint(2, Paint.Style.FILL, bottomLineColor);        borderPaint = getPaint(3, Paint.Style.STROKE, borderColor);        divideLinePaint = getPaint(divideLineWidth, Paint.Style.FILL, borderColor);    }    /**     * 设置画笔     *     * @param strokeWidth 画笔宽度     * @param style       画笔风格     * @param color       画笔颜色     * @return     */    private Paint getPaint(int strokeWidth, Paint.Style style, int color) {        Paint paint = new Paint(ANTI_ALIAS_FLAG);        paint.setStrokeWidth(strokeWidth);        paint.setStyle(style);        paint.setColor(color);        paint.setAntiAlias(true);        return paint;    }    @Override    protected void onSizeChanged(int w, int h, int oldw, int oldh) {        super.onSizeChanged(w, h, oldw, oldh);        height = h;        width = w;        divideLineWStartX = w / maxCount;        startX = w / maxCount / 2;        startY = h / 2;        bottomLineLength = w / (maxCount + 2);        rectF.set(0, 0, width, height);    }    @Override    protected void onDraw(Canvas canvas) {        //不删除的画会默认绘制输入的文字//       super.onDraw(canvas);        switch (psdType) {            case psdType_weChat:                drawWeChatBorder(canvas);                drawItemFocused(canvas, position);                break;            case psdType_bottomLine:                drawBottomBorder(canvas);                break;        }        drawPsdCircle(canvas);    }    /**     * 画微信支付密码的样式     *     * @param canvas     */    private void drawWeChatBorder(Canvas canvas) {        canvas.drawRoundRect(rectF, rectAngle, rectAngle, borderPaint);        for (int i = 0; i < maxCount - 1; i++) {            canvas.drawLine((i + 1) * divideLineWStartX,                    0,                    (i + 1) * divideLineWStartX,                    height,                    divideLinePaint);        }    }    private void drawItemFocused(Canvas canvas, int position) {        if (position > maxCount - 1) {            return;        }        focusedRecF.set(position * divideLineWStartX, 0, (position + 1) * divideLineWStartX,                height);        canvas.drawRoundRect(focusedRecF, rectAngle, rectAngle, getPaint(3, Paint.Style.STROKE, focusedColor));    }    /**     * 画底部显示的分割线     *     * @param canvas     */    private void drawBottomBorder(Canvas canvas) {        for (int i = 0; i < maxCount; i++) {            cX = startX + i * 2 * startX;            canvas.drawLine(cX - bottomLineLength / 2,                    height,                    cX + bottomLineLength / 2,                    height, bottomLinePaint);        }    }    /**     * 画密码实心圆     *     * @param canvas     */    private void drawPsdCircle(Canvas canvas) {        for (int i = 0; i < textLength; i++) {            canvas.drawCircle(startX + i * 2 * startX,                    startY,                    radius,                    circlePaint);        }    }    @Override    protected void onTextChanged(CharSequence text, int start, int lengthBefore, int lengthAfter) {        super.onTextChanged(text, start, lengthBefore, lengthAfter);        this.position = start + lengthAfter;        textLength = text.toString().length();        if (textLength>0&&textLength == maxCount) {            mListener.getInput(getPasswordString());        }        invalidate();    }    @Override    protected void onSelectionChanged(int selStart, int selEnd) {        super.onSelectionChanged(selStart, selEnd);        //保证光标始终在最后        if (selStart == selEnd) {            setSelection(getText().length());        }    }    /**     * 获取输入的密码     *     * @return     */    public String getPasswordString() {        return getText().toString().trim();    }    public void getComparePassword(onPasswordListener listener) {        mListener = listener;    }    /**     * 密码监听     */    public interface onPasswordListener {        void getInput(String data);    }}

5.调用 MainActivity

package com.example.mama.paydemo;import android.content.Context;import android.graphics.drawable.ColorDrawable;import android.support.v7.app.AlertDialog;import android.support.v7.app.AppCompatActivity;import android.os.Bundle;import android.view.Display;import android.view.Gravity;import android.view.LayoutInflater;import android.view.View;import android.view.Window;import android.view.WindowManager;import android.view.inputmethod.InputMethodManager;import android.widget.Button;import android.widget.TextView;import android.widget.Toast;import com.example.mama.paydemo.widget.PayPsdInputView;/** * Created by dingkangkang on 2017/12/5. */public class MainActivity extends AppCompatActivity {    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);    }    public void zhifu(View view){        final AlertDialog dialog = new AlertDialog.Builder(this).create();        Window w = dialog.getWindow();        w.setGravity(Gravity.BOTTOM);        //给弹窗加滑出动画        w.setWindowAnimations(R.style.DialogAnimation);        //设置外围点击消失        dialog.setCanceledOnTouchOutside(true);        //加上会去掉边界        dialog.getWindow().setBackgroundDrawable(new ColorDrawable());        dialog.show();        //以下必须写在show之后,不然会失效        WindowManager wm = w.getWindowManager();        Display d = wm.getDefaultDisplay();//屏幕        WindowManager.LayoutParams p = w.getAttributes();        p.width = (int)(d.getWidth()*1);//设置弹窗宽度为屏幕的宽度        w.setAttributes(p);        View v = LayoutInflater.from(this).inflate(R.layout.dialog_confirm_order,null);        dialog.setContentView(v);//给弹窗加载布局        TextView tv_close = (TextView)v.findViewById(R.id.tv_close);        Button btn_confirmorder = (Button)v.findViewById(R.id.btn_confirmorder);        btn_confirmorder.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View v) {                dialog.dismiss();                showPayDialog();            }        });        tv_close.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View v) {                dialog.dismiss();            }        });    }    //输入密码弹窗    public void showPayDialog(){        final AlertDialog dialog = new AlertDialog.Builder(this).create();        Window w = dialog.getWindow();        w.setGravity(Gravity.BOTTOM);        //给弹窗加滑出动画        w.setWindowAnimations(R.style.DialogAnimation);        //设置外围点击消失        dialog.setCanceledOnTouchOutside(true);        //加上会去掉边界        dialog.getWindow().setBackgroundDrawable(new ColorDrawable());        dialog.show();        //以下必须写在show之后,不然会失效        WindowManager wm = w.getWindowManager();        Display d = wm.getDefaultDisplay();//屏幕        WindowManager.LayoutParams p = w.getAttributes();        p.width = (int)(d.getWidth()*1);//设置弹窗宽度为屏幕的宽度        w.setAttributes(p);        View v = LayoutInflater.from(this).inflate(R.layout.dialog_input_password,null);        dialog.setContentView(v);//给弹窗加载布局        TextView tv_close = (TextView)v.findViewById(R.id.tv_close);        PayPsdInputView payPsdInputView = (PayPsdInputView)v.findViewById(R.id.et_password);        //弹出软键盘, AlertDialog中一般的显示方法不起作用        dialog.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM);        final InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);        imm.toggleSoftInput(InputMethodManager.SHOW_FORCED,0);        payPsdInputView.getComparePassword(new PayPsdInputView.onPasswordListener() {            @Override            public void getInput(String data) {                //此步骤要在 dialog.dismiss(); 之前执行,不然会失效                if (imm.isActive()){                    hideSoft();                }                dialog.dismiss();                Toast.makeText(getApplication(),"密码:::::"+data, Toast.LENGTH_SHORT).show();            }        });        tv_close.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View v) {                //此步骤要在 dialog.dismiss(); 之前执行,不然会失效                if (imm.isActive()){                    hideSoft();                }                dialog.dismiss();            }        });    }    //隐藏软键盘    private void hideSoft() {        //隐藏键盘,AlertDialog中一般的隐藏方法不起作用        InputMethodManager imm2 = (InputMethodManager) getSystemService(MainActivity.INPUT_METHOD_SERVICE);        imm2.toggleSoftInput(InputMethodManager.HIDE_NOT_ALWAYS, 0);    }}

6.弹窗动画 请看

7.自定义动画属性    在values下新建  attr.xml

<?xml version="1.0" encoding="utf-8"?><resources>    <!-- 支付属性 -->    <declare-styleable name="PayPsdInputView">        <attr name="maxCount" format="integer" />        <attr name="circleColor" format="color" />        <attr name="bottomLineColor" format="color" />        <attr name="radius" format="reference" />        <attr name="divideLineWidth" format="dimension" />        <attr name="divideLineColor" format="color" />        <attr name="rectAngle" format="dimension" />        <attr name="focusedColor" format="color"/>        <attr name="psdType" format="enum">            <enum name="weChat" value="0" />            <enum name="bottomLine" value="1" />        </attr>    </declare-styleable>    <declare-styleable name="CircleProgressBarView">        <attr name="circleBgStrokeWidth" format="dimension" />        <attr name="progressStrokeWidth" format="dimension" />        <attr name="circleBgColor" format="color" />        <attr name="progressColor" format="color" />        <attr name="circleAnimationDuration" format="integer" />        <attr name="isDrawCenterProgressText" format="boolean" />        <attr name="centerProgressTextColor" format="color"/>        <attr name="centerProgressTextSize" format="dimension"/>    </declare-styleable>    <declare-styleable name="RadarWaveView">        <attr name="waveColor" format="color" />        <attr name="waveAmplitude" format="dimension" />        <attr name="waveSpeed" format="float" />        <attr name="waveStartPeriod" format="float" />        <attr name="waveStart" format="boolean" />        <attr name="waveFillTop" format="boolean" />        <attr name="waveFillBottom" format="boolean" />        <attr name="waveFillType" format="enum">            <enum name="top" value="0" />            <enum name="bottom" value="1" />        </attr>        <attr name="waveType" format="enum">            <enum name="sin" value="0" />            <enum name="cos" value="1" />        </attr>    </declare-styleable></resources>


8.源码


9.特别感谢




原创粉丝点击