MyApp
Introduction: 使用 DialogFragment 代替 Dialog 和 PopupWindow 实现自定义的弹出框
Tags:
DialogFragment-底部弹出框-安全密码框-支付宝微信密码验证-1 效果图
自定义的 view 验证密码框
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