就是这种效果,有几个要求:
1、使用的不是定制的键盘,而是系统自带的键盘。
2、显示是四个分开的数字,但可以连续输入,按删除按钮会逐个删除,用户**无法**通过点击选取其中某个进行单独修改。
不知道有没有现成的控件,或者用什么方法可以实现。我现在脑袋有点僵了,想不出来。求大神赐教。
就是这种效果,有几个要求:
1、使用的不是定制的键盘,而是系统自带的键盘。
2、显示是四个分开的数字,但可以连续输入,按删除按钮会逐个删除,用户**无法**通过点击选取其中某个进行单独修改。
不知道有没有现成的控件,或者用什么方法可以实现。我现在脑袋有点僵了,想不出来。求大神赐教。
效果图:
直接把类复制进去 把属性放到values下的attrs.xml文件中 即可使用,下划线的颜色可自行定义
示例:
<VerifyCodeNumView
android:id="@+id/icv"
android:layout_width="match_parent"
android:layout_height="54dp"
android:layout_marginTop="32dp"
android:focusable="true"
app:icv_et_bg_focus="@drawable/shape_code_et_bg_focus"
app:icv_et_bg_normal="@drawable/shape_code_et_bg_normal"
app:icv_et_number="4"
app:icv_et_text_color="#404040"
app:icv_et_text_size="27dp"
app:icv_et_width="54dp"/>
类:
public class VerifyCodeNumView extends RelativeLayout {
private static final String TAG = VerifyCodeNumView.class.getSimpleName();
private LinearLayout containerEt;
private EditText et;
// 输入框数量
private int mEtNumber;
// 输入框的宽度
private int mEtWidth;
//输入框分割线
private Drawable mEtDividerDrawable;
//输入框文字颜色
private int mEtTextColor;
//输入框文字大小
private float mEtTextSize;
//输入框获取焦点时背景
private Drawable mEtBackgroundDrawableFocus;
// 输入框没有焦点时背景
private Drawable mEtBackgroundDrawableNormal;
//存储TextView的数据 数量由自定义控件的属性传入
private EditText[] mTextViews;
private MyTextWatcher myTextWatcher = new MyTextWatcher();
private InputMethodManager imm;
public VerifyCodeNumView(Context context) {
this(context, null);
}
public VerifyCodeNumView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public VerifyCodeNumView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(context, attrs, defStyleAttr);
}
//初始化 布局和属性
private void init(Context context, AttributeSet attrs, int defStyleAttr) {
LayoutInflater.from(context).inflate(R.layout.layout_identify_num_code, this);
containerEt = (LinearLayout) this.findViewById(R.id.container_et);
et = (EditText) this.findViewById(R.id.et);
TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.VerificationCodeView, defStyleAttr, 0);
mEtNumber = typedArray.getInteger(R.styleable.VerificationCodeView_icv_et_number, 1);
mEtWidth = typedArray.getDimensionPixelSize(R.styleable.VerificationCodeView_icv_et_width, 42);
mEtDividerDrawable = typedArray.getDrawable(R.styleable.VerificationCodeView_icv_et_divider_drawable);
mEtTextSize = typedArray.getDimensionPixelSize(R.styleable.VerificationCodeView_icv_et_text_size, 16);
mEtTextColor = typedArray.getColor(R.styleable.VerificationCodeView_icv_et_text_color, Color.BLACK);
mEtBackgroundDrawableFocus = typedArray.getDrawable(R.styleable.VerificationCodeView_icv_et_bg_focus);
mEtBackgroundDrawableNormal = typedArray.getDrawable(R.styleable.VerificationCodeView_icv_et_bg_normal);
//释放资源
typedArray.recycle();
Log.d(TAG, "mEtTextSize:"+mEtTextSize);
// 当xml中未配置时 这里进行初始配置默认图片
// if (mEtDividerDrawable == null) {
// mEtDividerDrawable = context.getResources().getDrawable(R.drawable.shape_divider_identifying);
// }
if (mEtBackgroundDrawableFocus == null) {
mEtBackgroundDrawableFocus = context.getResources().getDrawable(R.drawable.shape_icv_et_bg_focus);
}
if (mEtBackgroundDrawableNormal == null) {
mEtBackgroundDrawableNormal = context.getResources().getDrawable(R.drawable.shape_icv_et_bg_normal);
}
imm = (InputMethodManager) getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
initUI();
}
// 初始UI
private void initUI() {
initTextViews(getContext(), mEtNumber, mEtWidth, mEtDividerDrawable, mEtTextSize, mEtTextColor);
initEtContainer(mTextViews);
setListener();
}
public void focule() {
et.requestFocus();
imm.showSoftInput(et, InputMethodManager.RESULT_UNCHANGED_SHOWN);
et.setSelection(et.getText().length());
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
// 设置当 高为 warpContent 模式时的默认值 为 50dp
int mHeightMeasureSpec = heightMeasureSpec;
int heightMode = MeasureSpec.getMode(mHeightMeasureSpec);
if (heightMode == MeasureSpec.AT_MOST) {
mHeightMeasureSpec = MeasureSpec.makeMeasureSpec((int) dp2px(50, getContext()), MeasureSpec.EXACTLY);
}
super.onMeasure(widthMeasureSpec, mHeightMeasureSpec);
}
//初始化TextView
private void initTextViews(Context context, int etNumber, int etWidth, Drawable etDividerDrawable, float etTextSize, int etTextColor) {
// 设置 editText 的输入长度
et.setCursorVisible(true);//将光标隐藏
et.setFilters(new InputFilter[]{new InputFilter.LengthFilter(etNumber)}); //最大输入长度
// 设置分割线的宽度
if (etDividerDrawable != null) {
etDividerDrawable.setBounds(0, 0, etDividerDrawable.getMinimumWidth(), etDividerDrawable.getMinimumHeight());
containerEt.setDividerDrawable(etDividerDrawable);
}
mTextViews = new EditText[etNumber];
for (int i = 0; i < mTextViews.length; i++) {
EditText textView = new EditText(context);
textView.setTextSize(TypedValue.COMPLEX_UNIT_PX, etTextSize);
textView.setTextColor(etTextColor);
textView.setWidth(etWidth);
textView.setHeight(etWidth);
textView.setCursorVisible(true);
textView.setBackgroundDrawable(mEtBackgroundDrawableNormal);
textView.setGravity(Gravity.CENTER);
textView.setFocusable(false);
textView.setTypeface(Typeface.DEFAULT_BOLD);
mTextViews[i] = textView;
}
}
//初始化存储TextView 的容器
private void initEtContainer(EditText[] mTextViews) {
for (int i = 0; i < mTextViews.length; i++) {
containerEt.addView(mTextViews[i]);
if (i < mTextViews.length - 1) {
LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(0, 1);
layoutParams.weight = 1;
containerEt.addView(new View(getContext()), layoutParams);
}
}
}
private void setListener() {
et.setOnTouchListener(new OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
if(event.getAction()==MotionEvent.ACTION_UP) {
imm.showSoftInput(et, InputMethodManager.RESULT_UNCHANGED_SHOWN);
et.setSelection(et.getText().length());
}
return true;
}
});
// 监听输入内容
et.addTextChangedListener(myTextWatcher);
}
// 给TextView 设置文字
private void setText(String inputContent) {
Log.d(TAG, "setText:"+et.getText().toString());
char[] chars = inputContent.toCharArray();
for (int i = 0; i < mTextViews.length; i++) {
EditText tv = mTextViews[i];
if (i < chars.length) {
tv.setText(String.valueOf(chars[i]));
}else {
tv.setText("");
}
if (i < chars.length) {
tv.setBackground(mEtBackgroundDrawableFocus);
}else {
tv.setBackground(mEtBackgroundDrawableNormal);
}
}
if (inputCompleteListener != null) {
inputCompleteListener.inputComplete();
}
}
StringBuffer buffer = new StringBuffer();
/**
* 获取输入文本
*
* @return string
*/
public String getInputContent() {
buffer.delete(0, buffer.length());
for (EditText tv : mTextViews) {
buffer.append(tv.getText().toString().trim());
}
return buffer.toString();
}
/**
* 删除输入内容
*/
public void clearInputContent() {
for (int i = 0; i < 4; i++) {
mTextViews[i].setBackground(mEtBackgroundDrawableNormal);
mTextViews[i].setText("");
}
et.setText("");
}
/**
* 设置输入框个数
* @param etNumber
*/
public void setEtNumber(int etNumber) {
this.mEtNumber = etNumber;
et.removeTextChangedListener(myTextWatcher);
containerEt.removeAllViews();
initUI();
}
/**
* 获取输入的位数
*
* @return int
*/
public int getEtNumber() {
return mEtNumber;
}
// 输入完成 和 删除成功 的监听
private InputCompleteListener inputCompleteListener;
public void setInputCompleteListener(InputCompleteListener inputCompleteListener) {
this.inputCompleteListener = inputCompleteListener;
}
public interface InputCompleteListener {
void inputComplete();
}
public float dp2px(float dpValue, Context context) {
return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
dpValue, context.getResources().getDisplayMetrics());
}
public float sp2px(float spValue, Context context) {
return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP,
spValue, context.getResources().getDisplayMetrics());
}
private class MyTextWatcher implements TextWatcher {
@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 editable) {
String inputStr = editable.toString();
setText(inputStr);
}
}
}
属性attr:
<declare-styleable name="VerificationCodeView">
<!--输入框的数量-->
<attr name="icv_et_number" format="integer" />
<!--输入框的宽度-->
<attr name="icv_et_width" format="dimension|reference" />
<!--输入框之间的分割线-->
<attr name="icv_et_divider_drawable" format="reference" />
<!--输入框文字颜色-->
<attr name="icv_et_text_color" format="color|reference" />
<!--输入框文字大小-->
<attr name="icv_et_text_size" format="dimension|reference" />
<!--输入框获取焦点时边框-->
<attr name="icv_et_bg_focus" format="reference" />
<!--输入框没有焦点时边框-->
<attr name="icv_et_bg_normal" format="reference" />
</declare-styleable>