Android自定义EditText,实现分割输入内容效果

例如,输入一组25位的序列号,希望分成5组,每组5个数字。效果如下图。 
 

Android中没有发现类似的空间,只好自己动手了。 

1.首先自定义控件继承EditText,实现相应方法。 
Java代码   收藏代码
  1. package com.example.sequencenumber;  
  2.   
  3. import android.content.Context;  
  4. import android.content.res.TypedArray;  
  5. import android.text.Editable;  
  6. import android.text.TextWatcher;  
  7. import android.util.AttributeSet;  
  8. import android.view.View;  
  9. import android.widget.EditText;  
  10.   
  11. /** 
  12.  * 分割输入框 
  13.  *  
  14.  * @author Administrator 
  15.  *  
  16.  */  
  17. public class DivisionEditText extends EditText {  
  18.   
  19.     /* 内容数组 */  
  20.     private String[] text;  
  21.     /* 数组实际长度 (内容+分隔符) */  
  22.     private Integer length;  
  23.     /* 允许输入的长度 */  
  24.     private Integer totalLength;  
  25.     /* 每组的长度 */  
  26.     private Integer eachLength;  
  27.     /* 分隔符 */  
  28.     private String delimiter;  
  29.     /* 占位符 */  
  30.     private String placeHolder;  
  31.   
  32.     public DivisionEditText(Context context) {  
  33.         super(context);  
  34.     }  
  35.   
  36.     public DivisionEditText(Context context, AttributeSet attrs) {  
  37.         super(context, attrs);  
  38.         try {  
  39.             // 初始化属性  
  40.             TypedArray typedArray = context.obtainStyledAttributes(attrs,  
  41.                     R.styleable.EditText);  
  42.             this.totalLength = typedArray.getInteger(  
  43.                     R.styleable.EditText_totalLength, 0);  
  44.             this.eachLength = typedArray.getInteger(  
  45.                     R.styleable.EditText_eachLength, 0);  
  46.             this.delimiter = typedArray  
  47.                     .getString(R.styleable.EditText_delimiter);  
  48.             if (this.delimiter == null || this.delimiter.length() == 0) {  
  49.                 this.delimiter = "-";  
  50.             }  
  51.             this.placeHolder = typedArray  
  52.                     .getString(R.styleable.EditText_placeHolder);  
  53.             if (this.placeHolder == null || this.placeHolder.length() == 0) {  
  54.                 this.placeHolder = " ";  
  55.             }  
  56.             typedArray.recycle();  
  57.   
  58.             // 初始化  
  59.             init();  
  60.   
  61.             // 内容变化监听  
  62.             this.addTextChangedListener(new DivisionTextWatcher());  
  63.             // 获取焦点监听  
  64.             this.setOnFocusChangeListener(new DivisionFocusChangeListener());  
  65.   
  66.         } catch (Exception e) {  
  67.             e.printStackTrace();  
  68.         }  
  69.     }  
  70.   
  71.     public DivisionEditText(Context context, AttributeSet attrs, int defStyle) {  
  72.         super(context, attrs, defStyle);  
  73.     }  
  74.   
  75.     /** 
  76.      * 初始化 
  77.      */  
  78.     public void init() {  
  79.         // 总共分几组  
  80.         int groupNum = 0;  
  81.         // 如果每组长度(除数)不为0,计算  
  82.         if (this.eachLength != 0) {  
  83.             groupNum = this.totalLength / this.eachLength;  
  84.         }  
  85.         // 实际长度  
  86.         length = this.totalLength + this.eachLength != 0 ? this.totalLength  
  87.                 + groupNum - 1 : 0;  
  88.         // 初始化数组  
  89.         text = new String[this.length];  
  90.         // 如果数组大小大于0,初始化里面内容  
  91.         // 空格占位,分隔符占位  
  92.         if (length > 0) {  
  93.             for (int i = 0; i < length; i++) {  
  94.                 if (i != 0 && (i + 1) % (this.eachLength + 1) == 0) {  
  95.                     text[i] = this.delimiter;  
  96.                 } else {  
  97.                     text[i] = placeHolder;  
  98.                 }  
  99.             }  
  100.             // 设置文本  
  101.             mySetText();  
  102.             // 设置焦点  
  103.             mySetSelection();  
  104.         }  
  105.     }  
  106.   
  107.     /** 
  108.      * 获取结果 
  109.      *  
  110.      * @return 
  111.      */  
  112.     public String getResult() {  
  113.         StringBuffer buffer = new StringBuffer();  
  114.         for (String item : text) {  
  115.             if (!placeHolder.equals(item) && !delimiter.equals(item)) {  
  116.                 buffer.append(item);  
  117.             }  
  118.         }  
  119.         return buffer.toString();  
  120.     }  
  121.   
  122.     /** 
  123.      * 文本监听 
  124.      *  
  125.      * @author Administrator 
  126.      *  
  127.      */  
  128.     private class DivisionTextWatcher implements TextWatcher {  
  129.   
  130.         @Override  
  131.         public void afterTextChanged(Editable s) {  
  132.   
  133.         }  
  134.   
  135.         @Override  
  136.         public void beforeTextChanged(CharSequence s, int start, int count,  
  137.                 int after) {  
  138.         }  
  139.   
  140.         @Override  
  141.         public void onTextChanged(CharSequence s, int start, int before,  
  142.                 int count) {  
  143.             // 如果当前长度小于数组长度,认为使用退格  
  144.             if (s.length() < length) {  
  145.                 // 光标所在位置  
  146.                 int index = DivisionEditText.this.getSelectionStart();  
  147.                 // 删除的字符  
  148.                 String deleteStr = text[index];  
  149.                 // 如果是分隔符,删除分隔符前一个  
  150.                 if (delimiter.equals(deleteStr)) {  
  151.                     index--;  
  152.                 }  
  153.                 // 置空  
  154.                 text[index] = placeHolder;  
  155.                 // 查看前一个是否为分隔符  
  156.                 if (index - 1 >= 0) {  
  157.                     if (delimiter.equals(text[index - 1])) {  
  158.                         index--;  
  159.                     }  
  160.                 }  
  161.                 // 设置文本  
  162.                 mySetText();  
  163.                 // 设置焦点  
  164.                 mySetSelection(index);  
  165.             }  
  166.             // 只能一个一个字符输入  
  167.             if (count == 1) {  
  168.                 // 从光标起始,是否还有空的位置  
  169.                 int index = isBlank(DivisionEditText.this.getSelectionStart());  
  170.                 // 如果还有  
  171.                 if (index != -1) {  
  172.                     // 输入框内的字符串  
  173.                     String allStr = s.toString();  
  174.                     // 输入的字符串  
  175.                     String inputStr = allStr.substring(start, start + count);  
  176.                     // 替换占位符  
  177.                     text[index] = inputStr;  
  178.                 }  
  179.                 // 设置文本  
  180.                 mySetText();  
  181.                 // 设置焦点  
  182.                 mySetSelection();  
  183.             }  
  184.         }  
  185.     }  
  186.   
  187.     /** 
  188.      * 获取焦点监听 
  189.      *  
  190.      * @author Administrator 
  191.      *  
  192.      */  
  193.     private class DivisionFocusChangeListener implements OnFocusChangeListener {  
  194.   
  195.         @Override  
  196.         public void onFocusChange(View v, boolean hasFocus) {  
  197.             if (hasFocus) {  
  198.                 // 设置焦点  
  199.                 mySetSelection(0);  
  200.             }  
  201.         }  
  202.     }  
  203.   
  204.     /** 
  205.      * 设置文本 
  206.      *  
  207.      * @param text 
  208.      */  
  209.     private void mySetText() {  
  210.         StringBuffer buffer = new StringBuffer();  
  211.         for (String item : text) {  
  212.             buffer.append(item);  
  213.         }  
  214.         // 设置文本  
  215.         setText(buffer);  
  216.     }  
  217.   
  218.     /** 
  219.      * 设置焦点 
  220.      *  
  221.      * @param text 
  222.      */  
  223.     private void mySetSelection() {  
  224.         mySetSelection(fullSelection());  
  225.     }  
  226.   
  227.     /** 
  228.      * 设置焦点 
  229.      *  
  230.      * @param text 
  231.      */  
  232.     private void mySetSelection(int index) {  
  233.         DivisionEditText.this.setSelection(index);  
  234.     }  
  235.   
  236.     /** 
  237.      * 从光标位置起始,检查后面是否还有空的占位符 
  238.      *  
  239.      * @param text 
  240.      * @param selection 
  241.      * @return 
  242.      */  
  243.     private int isBlank(int selection) {  
  244.         int index = -1;  
  245.         for (int i = selection - 1; i < length; i++) {  
  246.             if (placeHolder.equals(text[i])) {  
  247.                 index = i;  
  248.                 break;  
  249.             }  
  250.         }  
  251.         return index;  
  252.     }  
  253.   
  254.     /** 
  255.      * 最后一个不空的字符后的光标位置 
  256.      *  
  257.      * @param text 
  258.      * @return 
  259.      */  
  260.     private int fullSelection() {  
  261.         int index = 0;  
  262.         for (int i = 0; i < length; i++) {  
  263.             if (!placeHolder.equals(text[i]) && !delimiter.equals(text[i])) {  
  264.                 index = i + 1;  
  265.             }  
  266.         }  
  267.         return index;  
  268.     }  
  269.   
  270.     public Integer getTotalLength() {  
  271.         return totalLength;  
  272.     }  
  273.   
  274.     public void setTotalLength(Integer totalLength) {  
  275.         this.totalLength = totalLength;  
  276.     }  
  277.   
  278.     public Integer getEachLength() {  
  279.         return eachLength;  
  280.     }  
  281.   
  282.     public void setEachLength(Integer eachLength) {  
  283.         this.eachLength = eachLength;  
  284.     }  
  285.   
  286.     public String getDelimiter() {  
  287.         return delimiter;  
  288.     }  
  289.   
  290.     public void setDelimiter(String delimiter) {  
  291.         this.delimiter = delimiter;  
  292.     }  
  293.   
  294.     public String getPlaceHolder() {  
  295.         return placeHolder;  
  296.     }  
  297.   
  298.     public void setPlaceHolder(String placeHolder) {  
  299.         this.placeHolder = placeHolder;  
  300.     }  
  301.   
  302. }  


2.在res/values下增加attrs.xml。 
Java代码   收藏代码
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <resources>  
  3.   
  4.     <declare-styleable name="EditText">  
  5.         <!-- 总共输入长度 -->  
  6.         <attr name="totalLength" format="integer" />  
  7.         <!-- 每组的长度 -->  
  8.         <attr name="eachLength" format="integer" />  
  9.         <!-- 分隔符 -->  
  10.         <attr name="delimiter" format="string" />  
  11.         <!-- 占位符 -->  
  12.         <attr name="placeHolder" format="string" />  
  13.     </declare-styleable>  
  14.   
  15. </resources>  


3.在布局文件中使用。 
Java代码   收藏代码
  1. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  2.     xmlns:tools="http://schemas.android.com/tools"  
  3.     xmlns:fsms="http://schemas.android.com/apk/res/com.example.sequencenumber"  
  4.     android:layout_width="match_parent"  
  5.     android:layout_height="match_parent"  
  6.     android:orientation="vertical" >  
  7.   
  8.     <com.example.sequencenumber.DivisionEditText  
  9.         android:layout_width="match_parent"  
  10.         android:layout_height="wrap_content"  
  11.         fsms:delimiter="-"  
  12.         fsms:eachLength="5"  
  13.         fsms:placeHolder="0"  
  14.         fsms:totalLength="25" />  
  15.   
  16. </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(总长度)为自定义的属性。 
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值