MyApp

Project Url: fanbaolong/MyApp
Introduction: 使用 DialogFragment 代替 Dialog 和 PopupWindow 实现自定义的弹出框
More: Author   ReportBugs   
Tags:
DialogFragment-底部弹出框-安全密码框-支付宝微信密码验证-

1 效果图

自定义的 view |240*400 验证密码框 |240*400 |240*400 |240*400

2 实现

文中使用了一个开源的自定义 BottomDialog

2.1 自定义的 view

MainActivity 中使用

 private void showButtomSelectDialog() {
        final BottomDialog mDialog = BottomDialog.create(getSupportFragmentManager());

        mDialog.setViewListener(new BottomDialog.ViewListener() {
            @Override
            public void bindView(View v) {
                TextView tv1 = (TextView) v.findViewById(R.id.pay_wechat_tv);
                TextView tv2 = (TextView) v.findViewById(R.id.pay_alipay_tv);

                tv1.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        Toast.makeText(MainActivity.this, "微信支付", Toast.LENGTH_SHORT).show();
                        mDialog.dismiss();
                    }
                });
                tv2.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        Toast.makeText(MainActivity.this, "支付宝支付", Toast.LENGTH_SHORT).show();
                        mDialog.dismiss();
                    }
                });
            }
        })
                .setLayoutRes(R.layout.buttom_select_dialog)
                .setDimAmount(0.6f)
                .setTag("BottomDialog")
                .show();

    }

buttom_select_dialog 布局文件

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

    <LinearLayout
        style="@style/fill_wrap"
        android:layout_alignParentBottom="true"
        android:background="@color/white"
        android:orientation="vertical" >

        <TextView
            style="@style/text_column"
            android:drawableLeft="@null"
            android:drawableRight="@null"
            android:gravity="center"
            android:text="请选择方式" />

        <View
            style="@style/h_line"
            android:layout_marginLeft="@dimen/dimens_10dp"
            android:layout_marginRight="@dimen/dimens_10dp" />

        <TextView
            android:id="@+id/pay_alipay_tv"
            style="@style/text_column"
            android:drawableLeft="@mipmap/icon_alipay_s"
            android:drawablePadding="@dimen/dimens_10dp"
            android:text="@string/scan_by_alipay" />

        <View
            style="@style/h_line"
            android:layout_marginLeft="@dimen/dimens_10dp"
            android:layout_marginRight="@dimen/dimens_10dp" />

        <TextView
            android:id="@+id/pay_wechat_tv"
            style="@style/text_column"
            android:drawableLeft="@mipmap/icon_wechat_s"
            android:drawablePadding="@dimen/dimens_10dp"
            android:text="@string/scan_by_wechat" />
    </LinearLayout>

</RelativeLayout>

2.2 密码框实现

自定义的密码框

public class ManagerPwdView implements OnClickListener{

    private Context mContext;

    private static int NUMBER_COUNT = 6;
    private final static String PASSWORD_NUMBER_SYMBOL = "●";

    private OnInputNumberCodeCallback mCallback; // 返回结果的回调
    private Stack<Integer> mStack;

    private View view;
    private TextView tv_payment_pwd;
    private TextView tv0;
    private TextView tv1;
    private TextView tv2;
    private TextView tv3;
    private TextView tv4;
    private TextView tv5;
    private TextView tv6;
    private TextView tv7;
    private TextView tv8;
    private TextView tv9;
    private TextView tv_clean;
    private RelativeLayout relat_del;
    private TextView tv_dismiss;
    private TextView tv_title;
    private ProgressBar progressBar;
    private int mType = 0;


    /**
     * @param mContext
     * @param type 0 为验证 1 为修改
     */
    public ManagerPwdView(Context mContext , int type) {
        this.mContext = mContext;
        this.mStack = new Stack<>();
        this.mType = type;
        initView();

    }


    @SuppressLint("InflateParams") 
    private void initView() {
        view = LayoutInflater.from(mContext).inflate(R.layout.view_payment_pwd, null);
        this.tv_payment_pwd = (TextView) view.findViewById(R.id.tv_payment_pwd);
        this.tv0 = (TextView) view.findViewById(R.id.tv0);
        this.tv1 = (TextView) view.findViewById(R.id.tv1);
        this.tv2 = (TextView) view.findViewById(R.id.tv2);
        this.tv3 = (TextView) view.findViewById(R.id.tv3);
        this.tv4 = (TextView) view.findViewById(R.id.tv4);
        this.tv5 = (TextView) view.findViewById(R.id.tv5);
        this.tv6 = (TextView) view.findViewById(R.id.tv6);
        this.tv7 = (TextView) view.findViewById(R.id.tv7);
        this.tv8 = (TextView) view.findViewById(R.id.tv8);
        this.tv9 = (TextView) view.findViewById(R.id.tv9);
        this.tv_clean = (TextView) view.findViewById(R.id.tv_clean);
        this.relat_del = (RelativeLayout) view.findViewById(R.id.relat_del);
        this.tv_dismiss = (TextView) view.findViewById(R.id.tv_dismiss);
        this.tv_title = (TextView) view.findViewById(R.id.tv_title);
        this.progressBar = (ProgressBar) view.findViewById(R.id.progressBar);

        if( mType == 0 )
            this.tv_title.setText("验证支付密码");
        else 
            this.tv_title.setText("设置支付密码");

        this.tv0.setOnClickListener(this);
        this.tv1.setOnClickListener(this);
        this.tv2.setOnClickListener(this);
        this.tv3.setOnClickListener(this);
        this.tv4.setOnClickListener(this);
        this.tv5.setOnClickListener(this);
        this.tv6.setOnClickListener(this);
        this.tv7.setOnClickListener(this);
        this.tv8.setOnClickListener(this);
        this.tv9.setOnClickListener(this);
        this.tv_clean.setOnClickListener(this);
        this.relat_del.setOnClickListener(this);
        this.tv_dismiss.setOnClickListener(this);

    }


    @Override
    public void onClick(View v) {
        switch (v.getId()) {
        case R.id.tv0:
            numberClick(0);
            break;
        case R.id.tv1:
            numberClick(1);
            break;
        case R.id.tv2:
            numberClick(2);
            break;
        case R.id.tv3:
            numberClick(3);
            break;
        case R.id.tv4:
            numberClick(4);
            break;
        case R.id.tv5:
            numberClick(5);
            break;
        case R.id.tv6:
            numberClick(6);
            break;
        case R.id.tv7:
            numberClick(7);
            break;
        case R.id.tv8:
            numberClick(8);
            break;
        case R.id.tv9:
            numberClick(9);
            break;
        case R.id.tv_clean:
            numberClick(10);
            break;
        case R.id.relat_del:
            numberClick(11);
            break;
        case R.id.tv_dismiss:
            mCallback.onClose();
            break;

        default:
            break;
        }
    }

    /**
     * 将点击事件传来
     * @param num
     */
    public void numberClick(int num){

        if (num == 10) {
            clearnNumber();
            return;
        }

        if( num <= 9){
            mStack.push(num);
        }else if(num == 11){
            deleteNumber();
        }

        refreshNumberViews(mStack);
        //input 6 numbers complete
        if (mStack.size() == NUMBER_COUNT) {
            StringBuilder codeBuilder = new StringBuilder();
            for (int number : mStack) {
                codeBuilder.append(number);
            }
            validation(codeBuilder.toString());
        }

    }

    /**
     * 验证字符串
     * @param string
     */
    private void validation(final String string) {
        progressBar.setVisibility(View.VISIBLE);


        new Handler().postDelayed(new Runnable() {

            @Override
            public void run() {
                clearnNumber();
                progressBar.setVisibility(View.GONE);
                if(string.equals("123456")) {
                    Toast.makeText(mContext, R.string.success, Toast.LENGTH_SHORT).show();
                    mCallback.onSuccess();
                }else {
                    Toast.makeText(mContext, R.string.failure, Toast.LENGTH_SHORT).show();
                }
            }
        }, 1000);
    }


    /**
     * 刷新输入框显示
     * @param mNumberStack
     */
    public void refreshNumberViews(Stack<Integer> mNumberStack) {
        StringBuffer numStr = new StringBuffer();

        for (int i = 0; i < mNumberStack.size(); i++) {
            numStr.append(PASSWORD_NUMBER_SYMBOL);
        }
        tv_payment_pwd.setText(numStr);
    }

    /**
     * 清空 mNumberStack 的内容并刷新密码格
     */
    public void clearnNumber() {
        mStack.clear();
        refreshNumberViews(mStack);
    }

    /**
     * 删除密码位数
     */
    public void deleteNumber() {
        if (mStack.empty() || mStack.size() > NUMBER_COUNT) {
            return;
        }
        mStack.pop();
    }

    /**
     * 返回输出的结果
     */
    public interface OnInputNumberCodeCallback {
        void onSuccess();
        void onClose();
    }

    public void setInputNumberCodeCallback(OnInputNumberCodeCallback callback) {
        this.mCallback = callback;
    }

    public View getView() {
        return view;
    }
    }

view_payment_pwd 布局文件

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical" >

    <LinearLayout
        style="@style/fill_wrap"
        android:layout_alignParentBottom="true"
        android:orientation="vertical" >

        <RelativeLayout
            style="@style/input_layout"
            android:layout_height="@dimen/dimens_50dp"
            android:background="@color/bg_gray" >

            <TextView
                android:id="@+id/tv_title"
                style="@style/wrap_wrap"
                android:layout_centerInParent="true"
                android:text=""
                android:textColor="@color/text_blue"
                android:textSize="@dimen/text_h3" />

            <TextView
                android:id="@+id/tv_dismiss"
                style="@style/wrap_wrap"
                android:layout_alignParentRight="true"
                android:layout_centerVertical="true"
                android:padding="@dimen/dimens_10dp"
                android:text="取消"
                android:textColor="@color/text_blue"
                android:textSize="@dimen/text_h3" />
        </RelativeLayout>

        <View
            style="@style/h_line"
            android:layout_height="@dimen/dimens_1dp" />

        <FrameLayout
            android:layout_width="match_parent"
            android:layout_height="@dimen/dimens_250dp" >

            <LinearLayout
                style="@style/fill_wrap"
                android:orientation="vertical" >

                <TextView
                    android:id="@+id/tv_payment_pwd"
                    style="@style/text_basic"
                    android:layout_height="@dimen/dimens_50dp"
                    android:background="@color/bg_gray"
                    android:gravity="center"
                    android:text=""
                    android:textColor="@color/black"
                    android:textSize="@dimen/text_h0" />

                <LinearLayout
                    style="@style/layout_payment_pwd"
                    android:orientation="horizontal" >

                    <TextView
                        android:id="@+id/tv1"
                        style="@style/text_full"
                        android:layout_gravity="center"
                        android:text="@string/number_1" />

                    <View style="@style/v_line" />

                    <TextView
                        android:id="@+id/tv2"
                        style="@style/text_full"
                        android:layout_gravity="center"
                        android:text="@string/number_2" />

                    <View style="@style/v_line" />

                    <TextView
                        android:id="@+id/tv3"
                        style="@style/text_full"
                        android:layout_gravity="center"
                        android:text="@string/number_3" />
                </LinearLayout>

                <View style="@style/h_line" />

                <LinearLayout
                    style="@style/layout_payment_pwd"
                    android:orientation="horizontal" >

                    <TextView
                        android:id="@+id/tv4"
                        style="@style/text_full"
                        android:layout_gravity="center"
                        android:text="@string/number_4" />

                    <View style="@style/v_line" />

                    <TextView
                        android:id="@+id/tv5"
                        style="@style/text_full"
                        android:layout_gravity="center"
                        android:text="@string/number_5" />

                    <View style="@style/v_line" />

                    <TextView
                        android:id="@+id/tv6"
                        style="@style/text_full"
                        android:layout_gravity="center"
                        android:text="@string/number_6" />
                </LinearLayout>

                <View style="@style/h_line" />

                <LinearLayout
                    style="@style/layout_payment_pwd"
                    android:orientation="horizontal" >

                    <TextView
                        android:id="@+id/tv7"
                        style="@style/text_full"
                        android:layout_gravity="center"
                        android:text="@string/number_7" />

                    <View style="@style/v_line" />

                    <TextView
                        android:id="@+id/tv8"
                        style="@style/text_full"
                        android:layout_gravity="center"
                        android:text="@string/number_8" />

                    <View style="@style/v_line" />

                    <TextView
                        android:id="@+id/tv9"
                        style="@style/text_full"
                        android:layout_gravity="center"
                        android:text="@string/number_9" />
                </LinearLayout>

                <View style="@style/h_line" />

                <LinearLayout
                    style="@style/layout_payment_pwd"
                    android:orientation="horizontal" >

                    <TextView
                        android:id="@+id/tv_clean"
                        style="@style/text_full"
                        android:layout_gravity="center"
                        android:background="@color/bg_gray"
                        android:text="@string/number_del" />

                    <View style="@style/v_line" />

                    <TextView
                        android:id="@+id/tv0"
                        style="@style/text_full"
                        android:layout_gravity="center"
                        android:text="@string/number_0" />

                    <View style="@style/v_line" />

                    <RelativeLayout
                        android:id="@+id/relat_del"
                        style="@style/text_full"
                        android:background="@color/bg_gray" >

                        <ImageView
                            style="@style/wrap_wrap"
                            android:layout_centerInParent="true"
                            android:contentDescription="@null"
                            android:src="@mipmap/ic_pay_del" />
                    </RelativeLayout>
                </LinearLayout>
            </LinearLayout>

            <ProgressBar
                android:id="@+id/progressBar"
                style="@style/fill_fill"
                android:layout_gravity="center"
                android:background="@color/bg_gray"
                android:indeterminateDrawable="@drawable/progressbar_style"
                android:visibility="gone" />
        </FrameLayout>
    </LinearLayout>

</RelativeLayout>

Mainactivity 中使用

 /**
     * 弹出密码验证界面
     */
    private void showVerifyDialog() {
        final BottomDialog mDialog = BottomDialog.create(getSupportFragmentManager());
        mDialog.setViewListener(new BottomDialog.ViewListener() {
            @Override
            public void bindView(View v) {

                FrameLayout frameLayout = (FrameLayout) v.findViewById(R.id.view_verify_framelayout);
                ManagerPwdView verifyView = new ManagerPwdView(MainActivity.this, 0);
                verifyView.setInputNumberCodeCallback(new ManagerPwdView.OnInputNumberCodeCallback() {

                    @Override
                    public void onSuccess() {
                        mDialog.dismiss();
                    }

                    @Override
                    public void onClose() {
                        mDialog.dismiss();
                    }
                });

                frameLayout.addView(verifyView.getView());
            }
        })
                .setLayoutRes(R.layout.buttom_fragment_layout)
                .setDimAmount(0.6f)
                .setTag("BottomDialog")
                .show();
    }

buttom_fragment_layout 布局文件,这里只有一个 Framelayout 方便弹出自定义的 dialogFragment 布局

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/view_verify_framelayout"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >
</FrameLayout>

关于密码框的,这里因为需求问题没有做文字框框,如果需要文字框框的,可以看下我 github 上另一个项目https://github.com/fanbaolong/TestPassword

Alt text

Apps
About Me
GitHub: Trinea
Facebook: Dev Tools