Android自定义EditText,实现分割输入内容效果
2014-06-03 14:53
891 查看
例如,输入一组25位的序列号,希望分成5组,每组5个数字。效果如下图。
![](https://oscdn.geek-share.com/Uploads/Images/Content/201908/20/3b24d89bf7937fa4b8a0dd0e899f2d2d.png)
Android中没有发现类似的空间,只好自己动手了。
1.首先自定义控件继承EditText,实现相应方法。
Java代码
![](https://oscdn.geek-share.com/Uploads/Images/Content/201908/20/371adac9e260dcac276b9429c936de84.png)
package com.example.sequencenumber;
import android.content.Context;
import android.content.res.TypedArray;
import android.text.Editable;
import android.text.TextWatcher;
import android.util.AttributeSet;
import android.view.View;
import android.widget.EditText;
/**
* 分割输入框
*
* @author Administrator
*
*/
public class DivisionEditText extends EditText {
/* 内容数组 */
private String[] text;
/* 数组实际长度 (内容+分隔符) */
private Integer length;
/* 允许输入的长度 */
private Integer totalLength;
/* 每组的长度 */
private Integer eachLength;
/* 分隔符 */
private String delimiter;
/* 占位符 */
private String placeHolder;
public DivisionEditText(Context context) {
super(context);
}
public DivisionEditText(Context context, AttributeSet attrs) {
super(context, attrs);
try {
// 初始化属性
TypedArray typedArray = context.obtainStyledAttributes(attrs,
R.styleable.EditText);
this.totalLength = typedArray.getInteger(
R.styleable.EditText_totalLength, 0);
this.eachLength = typedArray.getInteger(
R.styleable.EditText_eachLength, 0);
this.delimiter = typedArray
.getString(R.styleable.EditText_delimiter);
if (this.delimiter == null || this.delimiter.length() == 0) {
this.delimiter = "-";
}
this.placeHolder = typedArray
.getString(R.styleable.EditText_placeHolder);
if (this.placeHolder == null || this.placeHolder.length() == 0) {
this.placeHolder = " ";
}
typedArray.recycle();
// 初始化
init();
// 内容变化监听
this.addTextChangedListener(new DivisionTextWatcher());
// 获取焦点监听
this.setOnFocusChangeListener(new DivisionFocusChangeListener());
} catch (Exception e) {
e.printStackTrace();
}
}
public DivisionEditText(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
/**
* 初始化
*/
public void init() {
// 总共分几组
int groupNum = 0;
// 如果每组长度(除数)不为0,计算
if (this.eachLength != 0) {
groupNum = this.totalLength / this.eachLength;
}
// 实际长度
length = this.totalLength + this.eachLength != 0 ? this.totalLength
+ groupNum - 1 : 0;
// 初始化数组
text = new String[this.length];
// 如果数组大小大于0,初始化里面内容
// 空格占位,分隔符占位
if (length > 0) {
for (int i = 0; i < length; i++) {
if (i != 0 && (i + 1) % (this.eachLength + 1) == 0) {
text[i] = this.delimiter;
} else {
text[i] = placeHolder;
}
}
// 设置文本
mySetText();
// 设置焦点
mySetSelection();
}
}
/**
* 获取结果
*
* @return
*/
public String getResult() {
StringBuffer buffer = new StringBuffer();
for (String item : text) {
if (!placeHolder.equals(item) && !delimiter.equals(item)) {
buffer.append(item);
}
}
return buffer.toString();
}
/**
* 文本监听
*
* @author Administrator
*
*/
private class DivisionTextWatcher implements TextWatcher {
@Override
public void afterTextChanged(Editable s) {
}
@Override
public void beforeTextChanged(CharSequence s, int start, int count,
int after) {
}
@Override
public void onTextChanged(CharSequence s, int start, int before,
int count) {
// 如果当前长度小于数组长度,认为使用退格
if (s.length() < length) {
// 光标所在位置
int index = DivisionEditText.this.getSelectionStart();
// 删除的字符
String deleteStr = text[index];
// 如果是分隔符,删除分隔符前一个
if (delimiter.equals(deleteStr)) {
index--;
}
// 置空
text[index] = placeHolder;
// 查看前一个是否为分隔符
if (index - 1 >= 0) {
if (delimiter.equals(text[index - 1])) {
index--;
}
}
// 设置文本
mySetText();
// 设置焦点
mySetSelection(index);
}
// 只能一个一个字符输入
if (count == 1) {
// 从光标起始,是否还有空的位置
int index = isBlank(DivisionEditText.this.getSelectionStart());
// 如果还有
if (index != -1) {
// 输入框内的字符串
String allStr = s.toString();
// 输入的字符串
String inputStr = allStr.substring(start, start + count);
// 替换占位符
text[index] = inputStr;
}
// 设置文本
mySetText();
// 设置焦点
mySetSelection();
}
}
}
/**
* 获取焦点监听
*
* @author Administrator
*
*/
private class DivisionFocusChangeListener implements OnFocusChangeListener {
@Override
public void onFocusChange(View v, boolean hasFocus) {
if (hasFocus) {
// 设置焦点
mySetSelection(0);
}
}
}
/**
* 设置文本
*
* @param text
*/
private void mySetText() {
StringBuffer buffer = new StringBuffer();
for (String item : text) {
buffer.append(item);
}
// 设置文本
setText(buffer);
}
/**
* 设置焦点
*
* @param text
*/
private void mySetSelection() {
mySetSelection(fullSelection());
}
/**
* 设置焦点
*
* @param text
*/
private void mySetSelection(int index) {
DivisionEditText.this.setSelection(index);
}
/**
* 从光标位置起始,检查后面是否还有空的占位符
*
* @param text
* @param selection
* @return
*/
private int isBlank(int selection) {
int index = -1;
for (int i = selection - 1; i < length; i++) {
if (placeHolder.equals(text[i])) {
index = i;
break;
}
}
return index;
}
/**
* 最后一个不空的字符后的光标位置
*
* @param text
* @return
*/
private int fullSelection() {
int index = 0;
for (int i = 0; i < length; i++) {
if (!placeHolder.equals(text[i]) && !delimiter.equals(text[i])) {
index = i + 1;
}
}
return index;
}
public Integer getTotalLength() {
return totalLength;
}
public void setTotalLength(Integer totalLength) {
this.totalLength = totalLength;
}
public Integer getEachLength() {
return eachLength;
}
public void setEachLength(Integer eachLength) {
this.eachLength = eachLength;
}
public String getDelimiter() {
return delimiter;
}
public void setDelimiter(String delimiter) {
this.delimiter = delimiter;
}
public String getPlaceHolder() {
return placeHolder;
}
public void setPlaceHolder(String placeHolder) {
this.placeHolder = placeHolder;
}
}
2.在res/values下增加attrs.xml。
Java代码
![](https://oscdn.geek-share.com/Uploads/Images/Content/201908/20/371adac9e260dcac276b9429c936de84.png)
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="EditText">
<!-- 总共输入长度 -->
<attr name="totalLength" format="integer" />
<!-- 每组的长度 -->
<attr name="eachLength" format="integer" />
<!-- 分隔符 -->
<attr name="delimiter" format="string" />
<!-- 占位符 -->
<attr name="placeHolder" format="string" />
</declare-styleable>
</resources>
3.在布局文件中使用。
Java代码
![](https://oscdn.geek-share.com/Uploads/Images/Content/201908/20/371adac9e260dcac276b9429c936de84.png)
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:fsms="http://schemas.android.com/apk/res/com.example.sequencenumber"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<com.example.sequencenumber.DivisionEditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
fsms:delimiter="-"
fsms:eachLength="5"
fsms:placeHolder="0"
fsms:totalLength="25" />
</LinearLayout>
其中xmlns:fsms="http://schemas.android.com/apk/res/com.example.sequencenumber","com.example.sequencenumber"部分为R.java的包。其他部分是不变的。
fsms:delimiter(分隔符),fsms:eachLength(每组的长度),fsms:placeHolder(占位符),fsms:totalLength(总长度)为自定义的属性。
原文引自:http://renxin-327666062-qq-com.iteye.com/blog/1666694
![](https://oscdn.geek-share.com/Uploads/Images/Content/201908/20/3b24d89bf7937fa4b8a0dd0e899f2d2d.png)
Android中没有发现类似的空间,只好自己动手了。
1.首先自定义控件继承EditText,实现相应方法。
Java代码
![](https://oscdn.geek-share.com/Uploads/Images/Content/201908/20/371adac9e260dcac276b9429c936de84.png)
package com.example.sequencenumber;
import android.content.Context;
import android.content.res.TypedArray;
import android.text.Editable;
import android.text.TextWatcher;
import android.util.AttributeSet;
import android.view.View;
import android.widget.EditText;
/**
* 分割输入框
*
* @author Administrator
*
*/
public class DivisionEditText extends EditText {
/* 内容数组 */
private String[] text;
/* 数组实际长度 (内容+分隔符) */
private Integer length;
/* 允许输入的长度 */
private Integer totalLength;
/* 每组的长度 */
private Integer eachLength;
/* 分隔符 */
private String delimiter;
/* 占位符 */
private String placeHolder;
public DivisionEditText(Context context) {
super(context);
}
public DivisionEditText(Context context, AttributeSet attrs) {
super(context, attrs);
try {
// 初始化属性
TypedArray typedArray = context.obtainStyledAttributes(attrs,
R.styleable.EditText);
this.totalLength = typedArray.getInteger(
R.styleable.EditText_totalLength, 0);
this.eachLength = typedArray.getInteger(
R.styleable.EditText_eachLength, 0);
this.delimiter = typedArray
.getString(R.styleable.EditText_delimiter);
if (this.delimiter == null || this.delimiter.length() == 0) {
this.delimiter = "-";
}
this.placeHolder = typedArray
.getString(R.styleable.EditText_placeHolder);
if (this.placeHolder == null || this.placeHolder.length() == 0) {
this.placeHolder = " ";
}
typedArray.recycle();
// 初始化
init();
// 内容变化监听
this.addTextChangedListener(new DivisionTextWatcher());
// 获取焦点监听
this.setOnFocusChangeListener(new DivisionFocusChangeListener());
} catch (Exception e) {
e.printStackTrace();
}
}
public DivisionEditText(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
/**
* 初始化
*/
public void init() {
// 总共分几组
int groupNum = 0;
// 如果每组长度(除数)不为0,计算
if (this.eachLength != 0) {
groupNum = this.totalLength / this.eachLength;
}
// 实际长度
length = this.totalLength + this.eachLength != 0 ? this.totalLength
+ groupNum - 1 : 0;
// 初始化数组
text = new String[this.length];
// 如果数组大小大于0,初始化里面内容
// 空格占位,分隔符占位
if (length > 0) {
for (int i = 0; i < length; i++) {
if (i != 0 && (i + 1) % (this.eachLength + 1) == 0) {
text[i] = this.delimiter;
} else {
text[i] = placeHolder;
}
}
// 设置文本
mySetText();
// 设置焦点
mySetSelection();
}
}
/**
* 获取结果
*
* @return
*/
public String getResult() {
StringBuffer buffer = new StringBuffer();
for (String item : text) {
if (!placeHolder.equals(item) && !delimiter.equals(item)) {
buffer.append(item);
}
}
return buffer.toString();
}
/**
* 文本监听
*
* @author Administrator
*
*/
private class DivisionTextWatcher implements TextWatcher {
@Override
public void afterTextChanged(Editable s) {
}
@Override
public void beforeTextChanged(CharSequence s, int start, int count,
int after) {
}
@Override
public void onTextChanged(CharSequence s, int start, int before,
int count) {
// 如果当前长度小于数组长度,认为使用退格
if (s.length() < length) {
// 光标所在位置
int index = DivisionEditText.this.getSelectionStart();
// 删除的字符
String deleteStr = text[index];
// 如果是分隔符,删除分隔符前一个
if (delimiter.equals(deleteStr)) {
index--;
}
// 置空
text[index] = placeHolder;
// 查看前一个是否为分隔符
if (index - 1 >= 0) {
if (delimiter.equals(text[index - 1])) {
index--;
}
}
// 设置文本
mySetText();
// 设置焦点
mySetSelection(index);
}
// 只能一个一个字符输入
if (count == 1) {
// 从光标起始,是否还有空的位置
int index = isBlank(DivisionEditText.this.getSelectionStart());
// 如果还有
if (index != -1) {
// 输入框内的字符串
String allStr = s.toString();
// 输入的字符串
String inputStr = allStr.substring(start, start + count);
// 替换占位符
text[index] = inputStr;
}
// 设置文本
mySetText();
// 设置焦点
mySetSelection();
}
}
}
/**
* 获取焦点监听
*
* @author Administrator
*
*/
private class DivisionFocusChangeListener implements OnFocusChangeListener {
@Override
public void onFocusChange(View v, boolean hasFocus) {
if (hasFocus) {
// 设置焦点
mySetSelection(0);
}
}
}
/**
* 设置文本
*
* @param text
*/
private void mySetText() {
StringBuffer buffer = new StringBuffer();
for (String item : text) {
buffer.append(item);
}
// 设置文本
setText(buffer);
}
/**
* 设置焦点
*
* @param text
*/
private void mySetSelection() {
mySetSelection(fullSelection());
}
/**
* 设置焦点
*
* @param text
*/
private void mySetSelection(int index) {
DivisionEditText.this.setSelection(index);
}
/**
* 从光标位置起始,检查后面是否还有空的占位符
*
* @param text
* @param selection
* @return
*/
private int isBlank(int selection) {
int index = -1;
for (int i = selection - 1; i < length; i++) {
if (placeHolder.equals(text[i])) {
index = i;
break;
}
}
return index;
}
/**
* 最后一个不空的字符后的光标位置
*
* @param text
* @return
*/
private int fullSelection() {
int index = 0;
for (int i = 0; i < length; i++) {
if (!placeHolder.equals(text[i]) && !delimiter.equals(text[i])) {
index = i + 1;
}
}
return index;
}
public Integer getTotalLength() {
return totalLength;
}
public void setTotalLength(Integer totalLength) {
this.totalLength = totalLength;
}
public Integer getEachLength() {
return eachLength;
}
public void setEachLength(Integer eachLength) {
this.eachLength = eachLength;
}
public String getDelimiter() {
return delimiter;
}
public void setDelimiter(String delimiter) {
this.delimiter = delimiter;
}
public String getPlaceHolder() {
return placeHolder;
}
public void setPlaceHolder(String placeHolder) {
this.placeHolder = placeHolder;
}
}
2.在res/values下增加attrs.xml。
Java代码
![](https://oscdn.geek-share.com/Uploads/Images/Content/201908/20/371adac9e260dcac276b9429c936de84.png)
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="EditText">
<!-- 总共输入长度 -->
<attr name="totalLength" format="integer" />
<!-- 每组的长度 -->
<attr name="eachLength" format="integer" />
<!-- 分隔符 -->
<attr name="delimiter" format="string" />
<!-- 占位符 -->
<attr name="placeHolder" format="string" />
</declare-styleable>
</resources>
3.在布局文件中使用。
Java代码
![](https://oscdn.geek-share.com/Uploads/Images/Content/201908/20/371adac9e260dcac276b9429c936de84.png)
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:fsms="http://schemas.android.com/apk/res/com.example.sequencenumber"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<com.example.sequencenumber.DivisionEditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
fsms:delimiter="-"
fsms:eachLength="5"
fsms:placeHolder="0"
fsms:totalLength="25" />
</LinearLayout>
其中xmlns:fsms="http://schemas.android.com/apk/res/com.example.sequencenumber","com.example.sequencenumber"部分为R.java的包。其他部分是不变的。
fsms:delimiter(分隔符),fsms:eachLength(每组的长度),fsms:placeHolder(占位符),fsms:totalLength(总长度)为自定义的属性。
原文引自:http://renxin-327666062-qq-com.iteye.com/blog/1666694
相关文章推荐
- Android自定义EditText,实现分割输入内容效果
- Android中ClearEditText实现点击EditText输入框右边清除图标来清除输入内容的两种方式
- Android限制EditText只能输入中文或者指定内容的实现
- Android自定义Dialog,实现性别选择,日期选择,获取EditText内容
- Android实现EditText控件禁止输入内容的方法(附测试demo)
- Android中ClearEditText实现点击EditText输入框右边清除图标来清除输入内容的两种方式
- EditText实现分割输入内容
- Android 自定义EditText 实现获得焦点并且有内容显示右侧图片并点击清空内容
- android 实现edittext输入内容后可以点击右侧小图片进行清除内容
- android之EditText实现动态显示隐藏密码输入框的内容(实用)
- 自定义EditText实现未输入文字动画提醒效果
- Android限制EditText只能输入中文或者指定内容的实现
- Android 自定义 EditText 达到从右边输入的效果
- Android实现EditText文本的输入,通过点击按钮,获取输入的内容
- 自定义程序实现Android EditText只允许输入指定字符
- android Edittext自定义输入字符和类型
- Android UI 之居中绘制文本内容的正确方法——实现自定义一个TextView
- android 自定义ListView 实现 弹出自定义对话框(带EditText)实现 配置文件实现
- Android EditText中输入值以星号*显示 (密码的实现)
- 学习笔记-Android之ListView随EditText输入内容动态改变