自定义密码输入框和安全键盘
自定义密码输入框和安全键盘
自定义密码输入框
- 前言:
前边我写过一个高仿微信密码支付框的文章,那篇也是一个仿照微信支付样式的,但是在编码上是通过布局堆出那个样式的,这次是自定义一个控件,可以灵活的定制背景,边框颜色,输入文字的颜色和大小以及可输入的位数。 - 分析:
首先来看一下密码框的样式
n等分这个布局。明确我们输入的时候是在每个小框中显示的,所以edittext肯定不行。结合我上一篇的布局堆出的密码支付框样式来看。这里应该是水平分布的线性布局,n等分的n个textview和n-1个分割线线性分布。 -
自定义viewgroup:
自定义viewgroup继承LinearLayout,我们说了,要自己定义样式,颜色等等,那么我们就需要一个让用户自定义这些属性的方法。如下:// @param bgdrawable 背景drawable // @param pwdlength 密码长度 // @param splilinewidth 分割线宽度 // @param splilinecolor 分割线颜色 // @param pwdcolor 密码字体颜色 // @param pwdsize 密码字体大小 public void initStyle(int bgdrawable, int pwdlength, float splilinewidth, int splilinecolor, int pwdcolor, int pwdsize) { this.pwdlength = pwdlength; this.activity = (Activity) context; //根据自定义的属性来添加密码框 initShowInput(bgdrawable, pwdlength, splilinewidth, splilinecolor, pwdcolor, pwdsize); }
public void initShowInput(int bgcolor, int pwdlength, float slpilinewidth, int splilinecolor, int pwdcolor, int pwdsize) { this.setOrientation(HORIZONTAL); this.setBackgroundResource(bgcolor); //根据长度来初始化tv数组 textViews = new TextView[pwdlength]; LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(0, LayoutParams.MATCH_PARENT); params.weight = 1; params.gravity = Gravity.CENTER; //分割线的LayoutParams LinearLayout.LayoutParams params2 = new LinearLayout.LayoutParams(dip2px(context, slpilinewidth), LayoutParams.MATCH_PARENT); for (int i = 0; i < textViews.length; i++) { final int index = i; TextView textView = new TextView(context); textView.setGravity(Gravity.CENTER); textViews[i] = textView; textViews[i].setTextSize(pwdsize); textViews[i].setTextColor(context.getResources().getColor(pwdcolor)); textViews[i].setInputType(InputType.TYPE_NUMBER_VARIATION_PASSWORD | InputType.TYPE_CLASS_NUMBER); this.addView(textView, params); //设置分割线的宽高,并将其add if (i < textViews.length - 1) { View view = new View(context); view.setBackgroundColor(context.getResources().getColor(splilinecolor)); this.addView(view, params2); } } }
以上代码通过我们需要的属性,定义出样式。注释比较详细,不难看懂。到这里,基本的样式出来了,我们可以在布局中使用了。但样式只是基础,后续的操作还有很多。
-
对外暴露的一些基本操作的方法:
a、输入的字符串的展示:* 根据输入字符,显示密码个数 * * @param s public void initDatas(String s) { if (s.length() > 0) { int length = s.length(); if(length<=pwdlength){ for (int i = 0; i < pwdlength; i++) { if (i < length) { for (int j = 0; j < length; j++) { char ch = s.charAt(j); textViews[j].setText(String.valueOf(ch)); } } else { textViews[i].setText(""); } } if(length == pwdlength){ onTextFinishListener.onFinish(s); } } } else { for (int i = 0; i < pwdlength; i++) { textViews[i].setText(""); } } }
b、是否显示明文的控制:* 是否显示明文 * * @param showPwd public void setShowPwd(boolean showPwd) { int length = textViews.length; for (int i = 0; i < length; i++) { if (showPwd) { textViews[i].setTransformationMethod(PasswordTransformationMethod.getInstance()); } else { textViews[i].setTransformationMethod(HideReturnsTransformationMethod.getInstance()); } } }
c、清除文本public void clearText() { for (int i = 0; i < pwdlength; i++) { textViews[i].setText(""); } }
-
可供拓展的接口回调:比如输入完成的监听回调
public interface OnTextFinishListener { void onFinish(String str); }
到这里我们基本完成了对其的样式定制和拓展使用。需要注意的是,我们这里边只有textview,并没有输入框,如何调取键盘呢?所以如果你们对键盘没有特殊要求,那就在这个自定义viewgroup中new一个edittext并add进去。我这里为什么没有写,我前边也说了,这是结合安全键盘使用的,结合安全键盘使用的时候有一个和自带键盘的冲突,所以我不能写这些带有焦点弹出键盘的控件,我需要自己来控制我的安全键盘,所以没有写edittext。所以edittext的作用其实就是调出键盘,获取输入的内容。使用安全键盘,那安全键盘也需要做这些工作了。
自定义安全键盘
现在的安全键盘超级流行,一般是在输入密码,身份证等敏感信息的时候使用。
首先是布局,样式如下:
看布局我们可以使用gridview,也可以自己写。这个根据需要自己选择。我是自己写的,这样控制起来和点击交互效果相对好点。
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#ffffff"
android:orientation="vertical"
android:id="@+id/llCustomerKb"
android:divider="@drawable/divider_horizontal"
android:showDividers="beginning|middle">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#ffffff" >
<TextView
android:layout_width="wrap_content"
android:layout_height="16dp"
android:layout_centerInParent="true"
android:text="自定义安全键盘"/>
<ImageView
android:id="@+id/ivGlkHide"
android:layout_width="wrap_content"
android:layout_height="30dp"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"
android:paddingBottom="10dp"
android:paddingLeft="20dp"
android:paddingRight="20dp"
android:paddingTop="10dp"
android:src="@mipmap/icon_glk_arrow_down"
android:background="@drawable/press_style"/>
</RelativeLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:divider="@drawable/divider_horizontal"
android:showDividers="middle">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:orientation="horizontal"
android:divider="@drawable/divider_vertical"
android:showDividers="middle">
<Button
android:id="@+id/btGlkNum1"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:background="@drawable/selector_keyboard"
android:gravity="center"
android:text="1"
android:textColor="@color/global_black_color"
android:textSize="18sp" />
<Button
android:id="@+id/btGlkNum2"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:background="@drawable/selector_keyboard"
android:gravity="center"
android:text="2"
android:textColor="@color/global_black_color"
android:textSize="18sp" />
<Button
android:id="@+id/btGlkNum3"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:background="@drawable/selector_keyboard"
android:gravity="center"
android:text="3"
android:textColor="@color/global_black_color"
android:textSize="18sp" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:orientation="horizontal"
android:divider="@drawable/divider_vertical"
android:showDividers="middle" >
<Button
android:id="@+id/btGlkNum4"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:background="@drawable/selector_keyboard"
android:gravity="center"
android:text="4"
android:textColor="@color/global_black_color"
android:textSize="18sp" />
<Button
android:id="@+id/btGlkNum5"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:background="@drawable/selector_keyboard"
android:gravity="center"
android:text="5"
android:textColor="@color/global_black_color"
android:textSize="18sp" />
<Button
android:id="@+id/btGlkNum6"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:background="@drawable/selector_keyboard"
android:gravity="center"
android:text="6"
android:textColor="@color/global_black_color"
android:textSize="18sp" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:orientation="horizontal"
android:divider="@drawable/divider_vertical"
android:showDividers="middle">
<Button
android:id="@+id/btGlkNum7"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:background="@drawable/selector_keyboard"
android:gravity="center"
android:text="7"
android:textColor="@color/global_black_color"
android:textSize="18sp" />
<Button
android:id="@+id/btGlkNum8"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:background="@drawable/selector_keyboard"
android:gravity="center"
android:text="8"
android:textColor="@color/global_black_color"
android:textSize="18sp" />
<Button
android:id="@+id/btGlkNum9"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:background="@drawable/selector_keyboard"
android:gravity="center"
android:text="9"
android:textColor="@color/global_black_color"
android:textSize="18sp" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:orientation="horizontal"
android:divider="@drawable/divider_vertical"
android:showDividers="middle" >
<Button
android:id="@+id/btGlkNumDot"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:background="@drawable/selector_keyboard"
android:gravity="center"
android:text="·"
android:textColor="@color/global_black_color"
android:textSize="18sp" />
<Button
android:id="@+id/btGlkNum0"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:background="@drawable/selector_keyboard"
android:gravity="center"
android:text="0"
android:textColor="@color/global_black_color"
android:textSize="18sp" />
<ImageView
android:id="@+id/ivGlkDelete"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:background="#f2f2f2"
android:gravity="center"
android:paddingTop="10dp"
android:paddingBottom="10dp"
android:src="@mipmap/icon_glk_delete" />
</LinearLayout>
</LinearLayout>
</LinearLayout>
布局有了,include到我们需要的布局即可。接下来是对键盘的管理了。下一个keyBoardUtils来管理。明确一下需求,三种样式的,整数,小数和身份证的。左下角的按钮来匹配这三种形式。需要一个枚举类型来管理这三种样式。一个String类型的集合来管理输入的字符串。键盘显示隐藏时候的动画样式
代码解析:
首先构造方法里边,需要给出键盘的宽高。需要在这里管理每个键的点击,所以需要findViewById,因此需要给出键盘的parentView。需要知道键盘的显示样式,所以还需要枚举类型。
public KeyBoardUtils(Context context,View keyBoaardView,CUSTOME_KEYBOARD_TYPE type,int inputMaxLength) {
this.mcontext = context;
this.mkeyBoardView = keyBoaardView;
this.inputMaxLength = inputMaxLength;
this.mtype = type;
forbidClick = false;
//设置键盘的宽高
baseWidth = ViewUtils.getScreenWidth(context);
baseHeight = (int) (baseWidth*0.7);
RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) keyBoaardView.getLayoutParams();
params.height = baseHeight;
keyBoaardView.setLayoutParams(params);
//findView
findViews();
setKeyBoardType();
initListener();
}
我们点击的时候需要将当前点击的结果给view来展示,所以还需要拓展的接口回调
public interface KeyBoardClickInterface{
void clickNums(String str);
}
键盘按钮的点击事件的处理:
@Override
public void onClick(View view) {
switch (view.getId()){
case R.id.btGlkNum0:
//根据点击的内容来操作集合
addOrRemoveStrList(true,"0");
将当前集合的数据拼成字符串回调到view
keyBoardClickInterface.clickNums(getCurrentStr());
break;
case R.id.btGlkNum1:
addOrRemoveStrList(true,"1");
keyBoardClickInterface.clickNums(getCurrentStr());
break;
case R.id.btGlkNum2:
addOrRemoveStrList(true,"2");
keyBoardClickInterface.clickNums(getCurrentStr());
break;
case R.id.btGlkNum3:
addOrRemoveStrList(true,"3");
keyBoardClickInterface.clickNums(getCurrentStr());
break;
case R.id.btGlkNum4:
addOrRemoveStrList(true,"4");
keyBoardClickInterface.clickNums(getCurrentStr());
break;
case R.id.btGlkNum5:
addOrRemoveStrList(true,"5");
keyBoardClickInterface.clickNums(getCurrentStr());
break;
case R.id.btGlkNum6:
addOrRemoveStrList(true,"6");
keyBoardClickInterface.clickNums(getCurrentStr());
break;
case R.id.btGlkNum7:
addOrRemoveStrList(true,"7");
keyBoardClickInterface.clickNums(getCurrentStr());
break;
case R.id.btGlkNum8:
addOrRemoveStrList(true,"8");
keyBoardClickInterface.clickNums(getCurrentStr());
break;
case R.id.btGlkNum9:
addOrRemoveStrList(true,"9");
keyBoardClickInterface.clickNums(getCurrentStr());
break;
case R.id.ivGlkDelete:
addOrRemoveStrList(false,"");
keyBoardClickInterface.clickNums(getCurrentStr());
break;
case R.id.ivGlkHide:
hideKeyboard(true);
break;
case R.id.btGlkNumDot:
if(CUSTOME_KEYBOARD_TYPE.NUMBER != mtype){
addOrRemoveStrList(true,btGlkNumDot.getText().toString());
}
keyBoardClickInterface.clickNums(getCurrentStr());
break;
}
}
在view层的回调方法中将str给我们前边自定义的输入框来进行绘制。基本效果就出来了。
@Override
public void clickNums(String str) {
Log.e("TAG",str);
etPwd.initDatas(str);
}
到这里基本的功能已经实现了。如果有需要拓展的功能可以留言或私信。如有错误,敬请指正!需要源码的私信。
ps:整合的一个aar,直接可以使用aar下载
特别说明:安全键盘和输入框必须使用相对布局包裹!
上一篇: libvirtd 服务异常错误总结汇整