软件编程
位置:首页>> 软件编程>> Android编程>> Android自定义密码输入框和数字键盘

Android自定义密码输入框和数字键盘

作者:ganchuanpu  发布时间:2022-02-04 11:14:00 

标签:Android,输入框,数字键盘

实现了一个自定义的密码输入框和自定义数字键盘,用作用户支付密码设置界面。先上效果图如下,方格样式,以及点击空白处隐藏软键盘。

Android自定义密码输入框和数字键盘

控件实现清单:
1)集成于EditText的输入框控件:PasswordInputView.java
2)数字键盘工具类:NumKeyboardUtil.java
3)xml文件:number.xml
4)attrs样式
5)layout文件

具体内容:

PasswordInputView.java


public class PasswordInputView extends EditText{
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(Paint.ANTI_ALIAS_FLAG);
private Paint borderPaint = new Paint(Paint.ANTI_ALIAS_FLAG);

private final int defaultSplitLineWidth = 1;

public PasswordInputView(Context context, AttributeSet attrs) {
 super(context, attrs);
 final Resources res = getResources();

final int defaultBorderColor = res.getColor(R.color.line_color);
 final float defaultBorderWidth = res.getDimension(R.dimen.dimen_1px);
 final float defaultBorderRadius = res.getDimension(R.dimen.dimen_6);

final int defaultPasswordLength = 6;
 final int defaultPasswordColor = res.getColor(R.color.normal_text_color);
 final float defaultPasswordWidth = res.getDimension(R.dimen.dimen_6);
 final float defaultPasswordRadius = res.getDimension(R.dimen.dimen_6);

TypedArray a = context.getTheme().obtainStyledAttributes(attrs, R.styleable.PasswordInputView, 0, 0);
 try {
  borderColor = a.getColor(R.styleable.PasswordInputView_borderColor, defaultBorderColor);
  borderWidth = a.getDimension(R.styleable.PasswordInputView_borderWidth, defaultBorderWidth);
  borderRadius = a.getDimension(R.styleable.PasswordInputView_borderRadius, defaultBorderRadius);
  passwordLength = a.getInt(R.styleable.PasswordInputView_passwordLength, defaultPasswordLength);
  passwordColor = a.getColor(R.styleable.PasswordInputView_passwordColor, defaultPasswordColor);
  passwordWidth = a.getDimension(R.styleable.PasswordInputView_passwordWidth, defaultPasswordWidth);
  passwordRadius = a.getDimension(R.styleable.PasswordInputView_passwordRadius, defaultPasswordRadius);
 } finally {
  a.recycle();
 }

borderPaint.setStrokeWidth(borderWidth);
 borderPaint.setColor(borderColor);
 passwordPaint.setStrokeWidth(passwordWidth);
 passwordPaint.setStyle(Paint.Style.FILL);
 passwordPaint.setColor(passwordColor);

setSingleLine(true);
}

@Override
protected void onDraw(Canvas canvas) {
 int width = getWidth();
 int height = getHeight();

// 分割线
 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();
}
}

NumKeyboardUtil 数字软键盘工具类


public class NumKeyboardUtil {
private KeyboardView keyboardView;
private Keyboard k;// 数字键盘
private PasswordInputView ed;

public NumKeyboardUtil(Activity act, Context ctx, PasswordInputView edit) {
 this.ed = edit;
 k = new Keyboard(ctx, R.xml.number);
 keyboardView = (KeyboardView) act.findViewById(R.id.keyboard_view);
 keyboardView.setKeyboard(k);
 keyboardView.setEnabled(true);
 keyboardView.setPreviewEnabled(true);
 keyboardView.setOnKeyboardActionListener(listener);
}

private OnKeyboardActionListener listener = new OnKeyboardActionListener() {
 @Override
 public void swipeUp() {
 }

@Override
 public void swipeRight() {
 }

@Override
 public void swipeLeft() {
 }

@Override
 public void swipeDown() {
 }

@Override
 public void onText(CharSequence text) {
 }

@Override
 public void onRelease(int primaryCode) {
 }

@Override
 public void onPress(int primaryCode) {
 }
 //一些特殊操作按键的codes是固定的比如完成、回退等
 @Override
 public void onKey(int primaryCode, int[] keyCodes) {
   Editable editable = ed.getText();
   int start = ed.getSelectionStart();
   if (primaryCode == Keyboard.KEYCODE_DELETE) {// 回退
     if (editable != null && editable.length() > 0) {
       if (start > 0) {
         editable.delete(start - 1, start);
       }
     }
   }else if (primaryCode == Keyboard.KEYCODE_CANCEL) {// 完成
    hideKeyboard();
   } else { //将要输入的数字现在编辑框中
     editable.insert(start, Character.toString((char) primaryCode));
   }
 }
};

public void showKeyboard() {
 keyboardView.setVisibility(View.VISIBLE);
}

public void hideKeyboard() {
 keyboardView.setVisibility(View.GONE);
}

public int getKeyboardVisible() {
 return keyboardView.getVisibility();
}
}

number.xml
注意该文件需要放在项目下的res目录下的xml目录(没有就建个)里面


<?xml version="1.0" encoding="utf-8"?>
<Keyboard xmlns:android="http://schemas.android.com/apk/res/android"
android:horizontalGap="0px"
android:keyHeight="42dip"
android:keyWidth="31%p"
android:verticalGap="0px" >

<Row>
 <Key
  android:codes="49"
  android:keyLabel="1" />
 <Key
  android:codes="50"
  android:keyLabel="2" />
 <Key
  android:codes="51"
  android:keyLabel="3" />
</Row>

<Row>
 <Key
  android:codes="52"
  android:keyLabel="4" />
 <Key
  android:codes="53"
  android:keyLabel="5" />
 <Key
  android:codes="54"
  android:keyLabel="6" />
</Row>

<Row>
 <Key
  android:codes="55"
  android:keyLabel="7" />
 <Key
  android:codes="56"
  android:keyLabel="8" />
 <Key
  android:codes="57"
  android:keyLabel="9" />
</Row>

<Row>
 <Key
  android:codes="-3"
  android:keyLabel="完成" />
 <Key
  android:codes="48"
  android:keyLabel="0" />
 <Key
  android:codes="-5"
  android:keyIcon="@drawable/sym_keyboard_delete" />
</Row>

</Keyboard>

attrs.xml里面的样式:


<!-- 支付密码输入框 -->
<declare-styleable name="PasswordInputView">
 <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>

布局代码:


<?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="match_parent"
android:background="@color/main_bg_color" >

<include
 android:id="@+id/title_ll"
 layout="@layout/common_actionbar"/>

<TextView
 android:id="@+id/trader_pwd_set_tips_textview"
 style="@style/normal_text_style"
 android:layout_below="@+id/title_ll"
 android:layout_marginTop="25dip"
 android:layout_centerHorizontal="true"
 android:text="@string/trade_pwd_set_tips_text" />

<ImageView
 android:id="@+id/line1_imageview"
 style="@style/line_horizontal_style"
 android:layout_below="@+id/trader_pwd_set_tips_textview"
 android:layout_marginTop="26dip"
 android:contentDescription="@string/content_description" />

<com.acoe.demo.widget.PasswordInputView
 android:id="@+id/trader_pwd_set_pwd_edittext"
 android:layout_width="match_parent"
 android:layout_height="41dip"
 android:layout_below="@+id/line1_imageview"
 android:maxLength="6"
 android:background="@android:color/white" />

<ImageView
 android:id="@+id/line2_imageview"
 style="@style/line_horizontal_style"
 android:layout_below="@+id/trader_pwd_set_pwd_edittext"
 android:contentDescription="@string/content_description" />

<Button
 android:id="@+id/trader_pwd_set_next_button"
 style="@style/main_button_style"
 android:layout_below="@+id/line2_imageview"
 android:layout_marginTop="25dip"
 android:text="@string/trade_pwd_set_next_text" />

<android.inputmethodservice.KeyboardView
 android:id="@+id/keyboard_view"
 android:layout_width="match_parent"
 android:layout_height="240dip"
 android:layout_alignParentBottom="true"
 android:paddingTop="30dip"
 android:paddingLeft="13dip"
 android:paddingRight="13dip"
 android:focusable="true"
 android:focusableInTouchMode="true"
 android:visibility="invisible"/>

</RelativeLayout>

Activity代码片段:


//=======在Activity成员变量中声明部分代码=======
/** 控件 */
private PasswordInputView edtPwd;

//=======在Activity实例化控件部分代码=======
// 初始化控件
 edtPwd = (PasswordInputView) findViewById(R.id.trader_pwd_set_pwd_edittext);
 edtPwd.setInputType(InputType.TYPE_NULL); // 屏蔽系统软键盘
// 自定义软键盘
 if (keyboardUtil == null) keyboardUtil = new NumKeyboardUtil(this, this, edtPwd);
 edtPwd.setOnTouchListener(new OnTouchListener() {
  @Override
  public boolean onTouch(View v, MotionEvent event) {
   keyboardUtil.showKeyboard();
   return false;
  }
 });

//=======在Activity中重写onTouchEvent()方法,实现点击空白处隐藏软键盘=======
@Override
public boolean onTouchEvent(MotionEvent event) {
 if(event.getAction() == MotionEvent.ACTION_DOWN){
   if(getCurrentFocus()!=null && getCurrentFocus().getWindowToken()!=null){
    keyboardUtil.hideKeyboard();
   }
 }
 return super.onTouchEvent(event);
}

ps:如果把该密码输入框和其他类型输入框并用时要注意两者之间焦点变化时将系统软键盘和自定义的数字键盘隐藏,我的做法是给密码输入框绑定OnFacusChangeListener事件,来控制就好。如下:


edtPwd.setOnFocusChangeListener(new OnFocusChangeListener() {
  @Override
  public void onFocusChange(View v, boolean hasFocus) {
   if (hasFocus) {
    // 如果系统键盘是弹出状态,先隐藏
    ((InputMethodManager) getSystemService(INPUT_METHOD_SERVICE))
    .hideSoftInputFromWindow(getCurrentFocus()
    .getWindowToken(),
    InputMethodManager.HIDE_NOT_ALWAYS);
    keyboardUtil.showKeyboard();
   } else {
    keyboardUtil.hideKeyboard();
   }
  }
 });
0
投稿

猜你喜欢

手机版 软件编程 asp之家 www.aspxhome.com