自定义横线样式的密码输入控件


最近在写新项目有一个需求,重置密码的时候要求是六个输入横线来输入密码,效果如图所示:

自定义横线样式的密码输入控件自定义横线样式的密码输入控件

主要的代码逻辑就是设置每个EditText的输入监听,然后可以使用singleTextColor和singleTextSize,singleMarginLeft来设置想要的字体颜色和大小,控件距离左右边距的大小。singleNum可以选择用户想要展示的输入框个数,目前只支持4个和6个。下面是主要的代码,因为之前没有写过博客,排版可能不是太好。

package com.view.singledittextapplication;

import android.app.Activity;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Color;
import android.support.annotation.Nullable;
import android.text.Editable;
import android.text.TextWatcher;
import android.util.AttributeSet;
import android.util.Log;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputMethodManager;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.TextView;

/**
* Created by wkk on 2017/9/12.
*/

public class SingleEditText2 extends LinearLayout{

private LinearLayout ll_single;
private LayoutInflater mInflater;
private ViewGroup mEditText;
private EditText et_1;
private EditText et_2;
private EditText et_3;
private EditText et_4;
private EditText et_5;
private EditText et_6;
private int defalutColor;
private int defalutSize;
private CharSequence temp;
private CharSequence temp2;
private CharSequence temp3;
private CharSequence temp4;
private CharSequence temp5;
private CharSequence temp6;

private String num = "";
public SingleEditText2(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
mEditText = (ViewGroup) mInflater.inflate(R.layout.singleedittext2, null);
if (mEditText != null) {
addView(mEditText);
et_1 = (EditText) mEditText.findViewById(R.id.et_1);
et_2 = (EditText) mEditText.findViewById(R.id.et_2);
et_3 = (EditText) mEditText.findViewById(R.id.et_3);
et_4 = (EditText) mEditText.findViewById(R.id.et_4);
et_5 = (EditText) mEditText.findViewById(R.id.et_5);
et_6 = (EditText) mEditText.findViewById(R.id.et_6);
ll_single = (LinearLayout)mEditText.findViewById(R.id.ll_single);
}
//第二个参数就是我们在styles.xml文件中的<declare-styleable>标签
//即属性集合的标签,在R文件中名称为R.styleable+name
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.SingleEditText);
final int singleNum = a.getInteger(R.styleable.SingleEditText_singleNum, 6);
//第一个参数为属性集合里面的属性,R文件名称:R.styleable+属性集合名称+下划线+属性名称
//第二个参数为,如果没有设置这个属性,则设置的默认的值
int defaultMarginLeft = a.getDimensionPixelSize(R.styleable.SingleEditText_singleMarginLeft, 10);
defalutSize = a.getDimensionPixelSize(R.styleable.SingleEditText_singleTextSize, 33);
defalutColor = a.getColor(R.styleable.SingleEditText_singleTextColor, getResources().getColor(R.color.defaultTextColor));
a.recycle();
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, WindowManager.LayoutParams.WRAP_CONTENT);
params.setMargins(defaultMarginLeft,0,defaultMarginLeft,0);
ll_single.setLayoutParams(params);

et_1.setTextSize(defalutSize);
et_2.setTextSize(defalutSize);
et_3.setTextSize(defalutSize);
et_4.setTextSize(defalutSize);
et_5.setTextSize(defalutSize);
et_6.setTextSize(defalutSize);

et_1.setTextColor(defalutColor);
et_2.setTextColor(defalutColor);
et_3.setTextColor(defalutColor);
et_4.setTextColor(defalutColor);
et_5.setTextColor(defalutColor);
et_6.setTextColor(defalutColor);

if (singleNum == 4) {
et_5.setVisibility(View.GONE);
et_6.setVisibility(View.GONE);
}


et_1.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {

}

@Override
public void onTextChanged(CharSequence charSequence, int start, int brfore, int count) {
temp = charSequence;
}

@Override
public void afterTextChanged(Editable editable) {
int selectionStart = et_1.getSelectionStart();
int selectionEnd = et_1.getSelectionEnd();
et_1.setFocusable(false);
Log.e("wkk","temp.length:"+temp.length());
if (temp.length() > 1) {
editable.delete(selectionStart - 1, selectionEnd);
// et_2.setFocusableInTouchMode(true);
}
if(temp.length() == 0){
et_1.setFocusableInTouchMode(true);
}else if(temp.length() == 1){
et_2.setFocusableInTouchMode(true);
}
}
});
et_2.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {

}

@Override
public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
temp2 = charSequence;
}

@Override
public void afterTextChanged(Editable editable) {
int selectionStart = et_2.getSelectionStart();
int selectionEnd = et_2.getSelectionEnd();
et_2.setFocusable(false);
if (temp2.length() > 1) {
editable.delete(selectionStart - 1, selectionEnd);
}
if(temp2.length() == 0){
et_1.setFocusableInTouchMode(true);
}else if(temp2.length() == 1){
et_3.setFocusableInTouchMode(true);
}
}
});
et_3.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {

}

@Override
public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
temp3 = charSequence;
}

@Override
public void afterTextChanged(Editable editable) {
int selectionStart = et_3.getSelectionStart();
int selectionEnd = et_3.getSelectionEnd();
et_3.setFocusable(false);
// et_4.setFocusable(true);
if (temp3.length() > 1) {
editable.delete(selectionStart - 1, selectionEnd);
}
if(temp3.length() == 0){
et_2.setFocusableInTouchMode(true);
}else if(temp3.length() ==1){
et_4.setFocusableInTouchMode(true);
}
}
});
et_4.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {

}

@Override
public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
temp4 = charSequence;
}

@Override
public void afterTextChanged(Editable editable) {
int selectionStart = et_4.getSelectionStart();
int selectionEnd = et_4.getSelectionEnd();
if(singleNum == 4){
Log.e("wkk","temp6:"+ temp4.length());
if (temp4.length() > 1) {
editable.delete(selectionStart - 1, selectionEnd);
}
if(temp4.length() == 0){
et_4.setFocusable(false);
et_3.setFocusableInTouchMode(true);
}else if(temp4.length() == 1){
et_4.setFocusableInTouchMode(true);
}
}else{
et_4.setFocusable(false);
// et_5.setFocusable(true); 失去焦点,再用此方法获取不到,此方法与setFocusableInTouchMode(true),不能同时设置,会导致后者不能生效
if (temp4.length() > 1) {
editable.delete(selectionStart - 1, selectionEnd);
}
if(temp4.length() == 0){
et_3.setFocusableInTouchMode(true);
}else if(temp4.length() == 1){
et_5.setFocusableInTouchMode(true);
}
}
}
});
et_5.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {

}

@Override
public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
temp5 = charSequence;
}

@Override
public void afterTextChanged(Editable editable) {
int selectionStart = et_5.getSelectionStart();
int selectionEnd = et_5.getSelectionEnd();
et_5.setFocusable(false);
if (temp5.length() > 1) {
editable.delete(selectionStart - 1, selectionEnd);
}
if(temp5.length() == 0){
et_4.setFocusableInTouchMode(true);
}else if(temp5.length() == 1){
et_6.setFocusableInTouchMode(true);
}
}
});
et_6.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {

}

@Override
public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
temp6 = charSequence;
}

@Override
public void afterTextChanged(Editable editable) {
int selectionStart = et_6.getSelectionStart();
int selectionEnd = et_6.getSelectionEnd();
Log.e("wkk","temp6:"+ temp6.length());
if (temp6.length() > 1) {
editable.delete(selectionStart - 1, selectionEnd);
}
if(temp6.length() == 0){
et_6.setFocusable(false);
et_5.setFocusableInTouchMode(true);
}else if(temp6.length() == 1){
et_6.setFocusableInTouchMode(true);
}
}
});
}

public String getSingleText(){
num = "";
num+=et_1.getText().toString();
num+=et_2.getText().toString();
num+=et_3.getText().toString();
num+=et_4.getText().toString();
num+=et_5.getText().toString();
num+=et_6.getText().toString();
return num;
}
}

布局代码:

<?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="wrap_content"
android:gravity="center"
android:layout_marginLeft="@dimen/view_10_dp"
android:layout_marginRight="@dimen/view_10_dp"
android:id="@+id/ll_single"
android:orientation="horizontal">

<EditText
android:id="@+id/et_1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="center"
android:inputType="number"
android:textCursorDrawable="@color/default_white" />

<EditText
android:id="@+id/et_2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="@dimen/view_10_dp"
android:layout_weight="1"

android:focusable="false"
android:gravity="center"
android:inputType="number"
android:textCursorDrawable="@color/default_white" />

<EditText
android:id="@+id/et_3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="@dimen/view_10_dp"
android:layout_weight="1"
android:inputType="number"

android:focusable="false"
android:gravity="center"
android:textCursorDrawable="@color/default_white" />

<EditText
android:id="@+id/et_4"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="@dimen/view_10_dp"
android:layout_weight="1"

android:focusable="false"
android:inputType="number"
android:gravity="center"
android:textCursorDrawable="@color/default_white" />

<EditText
android:id="@+id/et_5"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="@dimen/view_10_dp"
android:layout_weight="1"
android:gravity="center"

android:focusable="false"
android:inputType="number"
android:textCursorDrawable="@color/default_white" />

<EditText
android:id="@+id/et_6"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="@dimen/view_10_dp"
android:layout_weight="1"
android:gravity="center"

android:focusable="false"
android:inputType="number"
android:textCursorDrawable="@color/default_white" />
</LinearLayout>

自定义的参数,也就是attrs里面需要写的:

<?xml version="1.0" encoding="utf-8"?>
<resources>
<attr name="singleTextColor" format="color"/>
<attr name="singleTextSize" format="dimension"/>
<attr name="singleMarginLeft" format="dimension"/>
<attr name="singleNum" format="integer"/>

<declare-styleable name="SingleEditText">
<attr name="singleTextColor"/>
<attr name="singleTextSize"/>
<attr name="singleMarginLeft"/>
<attr name="singleNum"/>
</declare-styleable>
</resources>

里面用到的color,dimens:

<color name="default_white">#ffffff</color>
<color name="defaultTextColor">#3a3a3a</color>

<dimen name="view_10_dp">10dp</dimen>
<dimen name="view_10_sp">10sp</dimen>
<dimen name="view_20_dp">20dp</dimen>
<dimen name="view_30_dp">30dp</dimen>

最后给大家上一下使用范例:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:gravity="center_horizontal"
tools:context="com.view.singledittextapplication.MainActivity">


<com.view.singledittextapplication.SingleEditText2
android:id="@+id/single"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
app:singleMarginLeft="@dimen/view_30_dp"
app:singleNum="4"></com.view.singledittextapplication.SingleEditText2>

<Button
android:id="@+id/getNum"
android:text="获取数字"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>

自定义横线样式的密码输入控件在Activity里面获取值得方法

final SingleEditText2 single = (SingleEditText2) findViewById(R.id.single);
findViewById(R.id.getNum).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Toast.makeText(MainActivity.this,single.getSingleText(),Toast.LENGTH_SHORT).show();
}
});
好了,以上就是所有了,如果使用过程中有什么问题欢迎一起讨论。