国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 系統 > Android > 正文

Android仿支付寶自定義密碼輸入框及安全鍵盤(密碼鍵盤)

2019-10-22 18:15:52
字體:
來源:轉載
供稿:網友

 0、前言

 之前做過的項目里有運用到一個支付場景:用戶辦理業務時需要輸入交易密碼,并且可根據平臺下發的支付方式進行選擇。這與支付寶的密碼輸入方式十分相似,如果使用Android系統或者第三方軟件的鍵盤,會有密碼泄露的風險。因此,大多數的應用軟件使用的是自定義的密碼輸入框及安全鍵盤。

 由于密碼輸入方式需要實現一個從底部彈出的效果,因此總體上決定采用BottomSheetDialog來進行封裝,同時為了提高安全性,還應該隨機生成鍵盤上的數字,界面如下圖所示:

android,支付寶,密碼輸入框,自定義密碼輸入框,密碼鍵盤 android,支付寶,密碼輸入框,自定義密碼輸入框,密碼鍵盤

 首先新建一個PasswordInputView類,將需要使用到的Context對象、支付金額、可支持的支付方式等數據,作為該類構造方法的參數進行傳遞。下文還將提到該類有一個回調方法,當用戶輸入的密碼滿足六位時,可以在回調方法中獲取密碼并顯示出來。PasswordInputView類的構造方法如下所示:

public PasswordInputView(Context context, String payMoney, List<String> payWayList) {  this.context = context;  this.payMoney = payMoney;  this.payWayList = payWayList;  payPwdDialog = new BottomSheetDialog(context);  View view = LayoutInflater.from(context).inflate(R.layout.dialog_pay_pwd, null, false);  initStep1(view);  initStep2(view);  llyPwdInputView = (LinearLayout) view.findViewById(R.id.lly_pwd_input_view);  llyPayWaySelect = (LinearLayout) view.findViewById(R.id.lly_pay_way_select);  showStep1(); // 顯示第一頁 } 

1、自定義密碼輸入框

 因為不能明文顯示輸入的密碼,所以使用“●”來代替每位密碼。自定義密碼輸入框涉及到的自定義屬性,主要包括:輸入框的大小、顏色、圓角半徑以及密碼圓點的大小、顏色、半徑。因此,自定義屬性attrs.xml文件如下所示:

<?xml version="1.0" encoding="utf-8"?> <resources>  <declare-styleable name="PasswordEditText">   <attr name="borderWidth" format="dimension"/>   <attr name="borderColor" format="color"/>   <attr name="borderRadius" format="dimension"/>   <attr name="passwordLength" format="integer"/>   <attr name="passwordWidth" format="dimension"/>   <attr name="passwordColor" format="color"/>   <attr name="passwordRadius" format="dimension"/>  </declare-styleable> </resources> 

 接下來就需要去繪制自定義控件了。首先獲取自定義屬性,然后在onDraw()中進行繪制,代碼如下所示:

package com.syd.paypwddialogdemo; import static android.graphics.Paint.ANTI_ALIAS_FLAG; import android.content.Context; import android.content.res.Resources; import android.content.res.TypedArray; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.graphics.RectF; import android.support.v7.widget.AppCompatEditText; import android.util.AttributeSet; /**  * 自定義密碼輸入框  */ public class PasswordEditText extends AppCompatEditText {  private int textLength;  private int borderColor;  private float borderWidth;  private float borderRadius;  private int passwordLength;  private int passwordColor;  private float passwordWidth;  private float passwordRadius;  private Paint passwordPaint = new Paint(ANTI_ALIAS_FLAG);  private Paint borderPaint = new Paint(ANTI_ALIAS_FLAG);  private final int defaultContMargin = 5;  private final int defaultSplitLineWidth = 3;  public PasswordEditText(Context context, AttributeSet attrs) {   super(context, attrs);   final Resources res = getResources();   final int defaultBorderColor = res.getColor(R.color.colorGray);   final float defaultBorderWidth = res.getDimension(R.dimen.default_ev_border_width);   final float defaultBorderRadius = res.getDimension(R.dimen.default_ev_border_radius);   final int defaultPasswordLength = res.getInteger(R.integer.default_ev_password_length);   final int defaultPasswordColor = res.getColor(R.color.colorBlack);   final float defaultPasswordWidth = res.getDimension(R.dimen.default_ev_password_width);   final float defaultPasswordRadius = res.getDimension(R.dimen.default_ev_password_radius);   TypedArray a = context.getTheme().obtainStyledAttributes(attrs, R.styleable.PasswordEditText, 0, 0);   try {    borderColor = a.getColor(R.styleable.PasswordEditText_borderColor, defaultBorderColor);    borderWidth = a.getDimension(R.styleable.PasswordEditText_borderWidth, defaultBorderWidth);    borderRadius = a.getDimension(R.styleable.PasswordEditText_borderRadius, defaultBorderRadius);    passwordLength = a.getInt(R.styleable.PasswordEditText_passwordLength, defaultPasswordLength);    passwordColor = a.getColor(R.styleable.PasswordEditText_passwordColor, defaultPasswordColor);    passwordWidth = a.getDimension(R.styleable.PasswordEditText_passwordWidth, defaultPasswordWidth);    passwordRadius = a.getDimension(R.styleable.PasswordEditText_passwordRadius, defaultPasswordRadius);   } finally {    a.recycle();   }   borderPaint.setStrokeWidth(borderWidth);   borderPaint.setColor(borderColor);   passwordPaint.setStrokeWidth(passwordWidth);   passwordPaint.setStyle(Paint.Style.FILL);   passwordPaint.setColor(passwordColor);  }  @Override  protected void onDraw(Canvas canvas) {   int width = getWidth();   int height = getHeight();   RectF rect = new RectF(0, 0, width, height);   borderPaint.setColor(borderColor);   canvas.drawRoundRect(rect, borderRadius, borderRadius, borderPaint);   RectF rectIn = new RectF(rect.left + defaultContMargin, rect.top + defaultContMargin,     rect.right - defaultContMargin, rect.bottom - defaultContMargin);   borderPaint.setColor(Color.WHITE);   canvas.drawRoundRect(rectIn, borderRadius, borderRadius, borderPaint);   borderPaint.setColor(borderColor);   borderPaint.setStrokeWidth(defaultSplitLineWidth);   for (int i = 1; i < passwordLength; i++) {    float x = width * i / passwordLength;    canvas.drawLine(x, 0, x, height, borderPaint);   }   float cx, cy = height / 2;   float half = width / passwordLength / 2;   for (int i = 0; i < textLength; i++) {    cx = width * i / passwordLength + half;    canvas.drawCircle(cx, cy, passwordWidth, passwordPaint);   }  }  @Override  protected void onTextChanged(CharSequence text, int start, int lengthBefore, int lengthAfter) {   super.onTextChanged(text, start, lengthBefore, lengthAfter);   this.textLength = text.toString().length();   invalidate();  }  public int getBorderColor() {   return borderColor;  }  public void setBorderColor(int borderColor) {   this.borderColor = borderColor;   borderPaint.setColor(borderColor);   invalidate();  }  public float getBorderWidth() {   return borderWidth;  }  public void setBorderWidth(float borderWidth) {   this.borderWidth = borderWidth;   borderPaint.setStrokeWidth(borderWidth);   invalidate();  }  public float getBorderRadius() {   return borderRadius;  }  public void setBorderRadius(float borderRadius) {   this.borderRadius = borderRadius;   invalidate();  }  public int getPasswordLength() {   return passwordLength;  }  public void setPasswordLength(int passwordLength) {   this.passwordLength = passwordLength;   invalidate();  }  public int getPasswordColor() {   return passwordColor;  }  public void setPasswordColor(int passwordColor) {   this.passwordColor = passwordColor;   passwordPaint.setColor(passwordColor);   invalidate();  }  public float getPasswordWidth() {   return passwordWidth;  }  public void setPasswordWidth(float passwordWidth) {   this.passwordWidth = passwordWidth;   passwordPaint.setStrokeWidth(passwordWidth);   invalidate();  }  public float getPasswordRadius() {   return passwordRadius;  }  public void setPasswordRadius(float passwordRadius) {   this.passwordRadius = passwordRadius;   invalidate();  } } 

2、安全鍵盤的實現

 安全鍵盤主要是通過GridView來實現,上文提到為了保證安全性,在安全鍵盤初始化的時候,應該隨機生成鍵盤上的數字,代碼如下所示:

/**  * 初始化密碼鍵盤  */ private void initKeyboard() {  final int number = 10;  int[] keys = new int[number];  for (int i = 0; i < 10; i++) {   keys[i] = i;  }  // 隨機生成鍵盤數字  Random random = new Random();  for (int i = 0; i < number; i++) {   int p = random.nextInt(number);   int tmp = keys[i];   keys[i] = keys[p];   keys[p] = tmp;  }  numList = new ArrayList<>();  for (int i = 0; i < 12; i++) {   Map<String, String> map = new HashMap<>();   if (i < 9) {    map.put("num", String.valueOf(keys[i]));   } else if (i == 9) {    map.put("num", "");   } else if (i == 10) {    map.put("num", String.valueOf(keys[9]));   } else if (i == 11) {    map.put("num", "");   }   numList.add(map);  }  KeyAdapter keyAdapter = new KeyAdapter(context, numList, handler);  gvKeyboard.setAdapter(keyAdapter); } 

 安全鍵盤點擊事件的處理,是在適配器KeyAdapter的構造方法中傳入Handler對象,通過收發消息的方式在PasswordInputView類中處理的,代碼如下所示:

holder.btnKey.setOnClickListener(new View.OnClickListener() {  @Override  public void onClick(View v) {   Message msg = new Message();   msg.what = Constants.KEYBOARD_INPUT;   msg.obj = position;   handler.sendMessage(msg);  } }); 

 Handler對象在PasswordInputView類中定義,主要用于處理安全鍵盤的點擊事件,代碼如下所示:

Handler handler = new Handler() {  @Override  public void dispatchMessage(Message msg) {   switch (msg.what) {    case Constants.KEYBOARD_INPUT:     int position = (int) msg.obj;     if (position < 11 && position != 9) {      // 點擊0-9按鍵      password = etPwd.getText().append(numList.get(position).get("num")).toString();      etPwd.setText(password);     } else {      if (position == 11) {       // 點擊退格鍵       if (!TextUtils.isEmpty(password) && !password.equals("")) {        password = etPwd.getText().delete(password.length() - 1, password.length()).toString();        etPwd.setText(password);       }      }     }     break;   }  } }; 

 為了方便外部獲取到用戶輸入的密碼,設計一個回調接口OnPwdInputListener,并在PasswordInputView類中為回調接口創建一個set方法,代碼如下所示:

package com.syd.paypwddialogdemo; public interface OnPwdInputListener {  void onPwdInput(String password); } 

 當PasswordEditText控件的TextWatcher對象監聽到輸入的密碼滿足六位時,調用回調方法,將密碼作為參數進行傳遞,代碼如下所示:

textWatcher = new TextWatcher() {  @Override  public void afterTextChanged(Editable s) {   if (etPwd.getText().length() == 6) {    onPwdInputListener.onPwdInput(etPwd.getText().toString());   }  } }; etPwd.addTextChangedListener(textWatcher); 

在外部調用set方法,創建OnPwdInputListener對象,重寫回調方法,即可獲取到用戶輸入的密碼,代碼如下所示:

pwdInputView.setOnPwdInputListener(new OnPwdInputListener() {  @Override  public void onPwdInput(String password) {   Toast.makeText(MainActivity.this, password, Toast.LENGTH_SHORT).show();  } }); 

3、結語

 以上介紹了自定義密碼輸入框及安全鍵盤的大致實現思路,對源碼感興趣的小伙伴可以點擊下載Demo,查看具體的實現過程及演示效果。


注:相關教程知識閱讀請移步到Android開發頻道。
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 渝北区| 施秉县| 云安县| 禄劝| 曲周县| 溧阳市| 屯门区| 汤阴县| 瑞丽市| 丰镇市| 扎赉特旗| 顺昌县| 克什克腾旗| 杂多县| 铁岭县| 明星| 荔浦县| 郓城县| 大兴区| 钟祥市| 互助| 许昌市| 天水市| 临澧县| 三河市| 高青县| 清远市| 永胜县| 台东市| 河津市| 鸡东县| 珲春市| 灵台县| 太白县| 楚雄市| 蒙山县| 博客| 青冈县| 高唐县| 抚松县| 新乡市|