在一些需要输入支付密码的需求中,如微信支付的黑圆点。
开始也是一直在想着怎么自定义EditText去做,确实网上已经有自定义view的实现。之前也是参考别人写的,并修改了部分后用于项目中,大家可以搜下“PasswordInputView”,好多作者实现了,大家的思路都差不多。不知道参考哪位作者的了,因为自己改了部分参数跟方法,修改了颜色,找不到对比踪迹了。
但是测试发现自定义的那个View第一个输入框总比其的5个大点点,要仔细看,然后密码输入框的线也有点粗细不一,边角跟设计图也不一致,测试就提bug单了。
后面想着怎么优化来着,继续在那个类上改来改去,边角上总有点跟设计图不一致,产品就没通过了。基础差,没办法。
停顿下,去厕所蹲下大便思考下......过不久,只听脑子里一个微波炉的声音响起:“叮”的一声,有思路了!
做一个假象!
就是:EditText文本输入透明、文字透明,然后盖在一个View上面,然后监控这个EditText的
afterTextChanged 处理EditText 下面的那个View相关的显示逻辑。
开干。
1、布局文件:dialog_pay.xml
Code Text:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:gravity="center" android:orientation="vertical" android:padding="15dp"> <LinearLayout android:layout_width="wrap_content" android:layout_height="wrap_content" android:background="@drawable/bg_white_rect_circle_border" android:orientation="vertical"> <RelativeLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:gravity="center_vertical" android:padding="8dp"> <ImageView android:id="@+id/dialog_close" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentRight="true" android:layout_marginLeft="-8dp" android:padding="15dp" android:src="@mipmap/ic_dialog_close" android:visibility="visible" /> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerInParent="true" android:text="请输入支付密码" android:textColor="@color/gray_general_lable" android:textSize="@dimen/text_size_l" /> </RelativeLayout> <View android:layout_width="match_parent" android:layout_height="0.5dp" android:background="@color/divider_color" /> <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginLeft="20dp" android:layout_marginRight="20dp" android:layout_marginTop="16dp" android:gravity="center_horizontal" android:text="支付金额" android:textColor="@color/gray_general_title" android:textSize="@dimen/text_size_m" /> <TextView android:id="@+id/dialog_money" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginLeft="20dp" android:layout_marginRight="20dp" android:gravity="center_horizontal" android:text="0" android:textColor="@color/black_general_title" android:textSize="22sp" /> <FrameLayout android:id="@+id/fragment_password" android:layout_width="match_parent" android:layout_height="wrap_content"> <LinearLayout android:layout_width="match_parent" android:layout_height="40dp" android:layout_margin="15dp" android:gravity="center" android:orientation="horizontal"> <ImageView android:id="@+id/et_pwd_1" style="@style/EditTextPasswordStyle" /> <ImageView android:id="@+id/et_pwd_2" style="@style/EditTextPasswordStyle" android:layout_marginLeft="10dp" /> <ImageView android:id="@+id/et_pwd_3" style="@style/EditTextPasswordStyle" android:layout_marginLeft="10dp" /> <ImageView android:id="@+id/et_pwd_4" style="@style/EditTextPasswordStyle" android:layout_marginLeft="10dp" /> <ImageView android:id="@+id/et_pwd_5" style="@style/EditTextPasswordStyle" android:layout_marginLeft="10dp" /> <ImageView android:id="@+id/et_pwd_6" style="@style/EditTextPasswordStyle" android:layout_marginLeft="10dp" /> </LinearLayout> <EditText android:id="@+id/et_pwd_real" android:layout_width="match_parent" android:layout_height="40dp" android:layout_margin="15dp" android:background="@color/color_transparent" android:cursorVisible="false" android:inputType="numberPassword" android:maxLength="6" android:maxLines="1" android:textColor="@color/color_transparent" /> </FrameLayout> </LinearLayout> </LinearLayout>
Code Design:
2、自定义Dialog:PayDialog.java
public class PayDialog extends Dialog implements View.OnClickListener { private TextView mDialogMoney; private EditText mEtPwdReal; private ImageView mEt1, mEt2, mEt3, mEt4, mEt5, mEt6; public interface PasswordCallback { void callback(String password); } public PasswordCallback mPasswordCallback; public PayDialog(Context context) { super(context, R.style.PasswordDialog); initDilaog(); } void initDilaog() { requestWindowFeature(Window.FEATURE_NO_TITLE); setContentView(R.layout.dialog_pay); setCancelable(false); setCanceledOnTouchOutside(false); findViewById(R.id.dialog_close).setOnClickListener(this); mDialogMoney = (TextView) findViewById(R.id.dialog_money); mEtPwdReal = (EditText) findViewById(R.id.et_pwd_real); mEtPwdReal.addTextChangedListener(new PasswordEditChangedListener(mEtPwdReal)); mEt1 = (ImageView) findViewById(R.id.et_pwd_1); mEt2 = (ImageView) findViewById(R.id.et_pwd_2); mEt3 = (ImageView) findViewById(R.id.et_pwd_3); mEt4 = (ImageView) findViewById(R.id.et_pwd_4); mEt5 = (ImageView) findViewById(R.id.et_pwd_5); mEt6 = (ImageView) findViewById(R.id.et_pwd_6); } private void requestFocus() { mEtPwdReal.requestFocus(); this.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE); } /** * 重制 */ public void clearPasswordText() { mEtPwdReal.setText(""); requestFocus(); } /** * 设置金额 * * @param money */ public void setMoney(int money) { mDialogMoney.setText("¥" + money + ".00"); } /** * 设置回调 * * @param passwordCallback */ public void setPasswordCallback(PasswordCallback passwordCallback) { this.mPasswordCallback = passwordCallback; } @Override public void onClick(View v) { switch (v.getId()) { case R.id.dialog_close: dismiss(); break; } } private class PasswordEditChangedListener implements TextWatcher { private EditText mEditText; public PasswordEditChangedListener(EditText editText) { this.mEditText = editText; } @Override public void beforeTextChanged(CharSequence s, int start, int count, int after) { } @Override public void onTextChanged(CharSequence s, int start, int before, int count) { } @Override public void afterTextChanged(Editable s) { String ret = s.toString().trim(); if (mEditText.getId() == R.id.et_pwd_real) { char[] array = ret.toCharArray(); for (int i = 0; i < array.length; i++) { //设置图片为黑色圆点 if (i == 0) { mEt1.setImageResource(R.mipmap.icon_pwd); } else if (i == 1) { mEt2.setImageResource(R.mipmap.icon_pwd); } else if (i == 2) { mEt3.setImageResource(R.mipmap.icon_pwd); } else if (i == 3) { mEt4.setImageResource(R.mipmap.icon_pwd); } else if (i == 4) { mEt5.setImageResource(R.mipmap.icon_pwd); } else if (i == 5) { mEt6.setImageResource(R.mipmap.icon_pwd); } } clearTextView(array.length, mEt1, mEt2, mEt3, mEt4, mEt5, mEt6); //自动提交 if (array.length == 6) { if (mPasswordCallback != null) mPasswordCallback.callback(String.valueOf(array)); } } } /** * 按删除键后,删除的值对应的图标还原 * * @param length * @param editTexts */ void clearTextView(int length, ImageView... editTexts) { for (int i = 0; i < 6; i++) { //比如当前密码长度为4位,当大于4的图标,就要还原成未输入情况 if (i > length - 1) { editTexts[i].setImageResource(0); } } } } }
3、调用Dialog:MainActivity.java
public class MainActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); findViewById(R.id.btn_pay).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { createPayDialog(); } }); } void createPayDialog() { final PayDialog payDialog = new PayDialog(this); payDialog.setMoney(520); payDialog.setPasswordCallback(new PayDialog.PasswordCallback() { @Override public void callback(String password) { if ("000000".equals(password)) { payDialog.clearPasswordText(); Toast.makeText(MainActivity.this, "密码为错误,请重试", Toast.LENGTH_SHORT).show(); } else { Toast.makeText(MainActivity.this, "密码为:" + password, Toast.LENGTH_SHORT).show(); payDialog.dismiss(); } } }); payDialog.clearPasswordText(); payDialog.show(); } }
4、运行效果图: