`
endual
  • 浏览: 3545609 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

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

 
阅读更多


http://renxin-327666062-qq-com.iteye.com/blog/1666694

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(总长度)为自定义的属性。 
分享到:
评论

相关推荐

    Android的edittext在弹出框中实现输入自动千分位分隔和金额限制

    这个自定义控件"Android的edittext在弹出框中实现输入自动千分位分隔和金额限制"就解决了这样的问题。 首先,我们需要理解的是`EditText`的基本用法。`EditText`是继承自`TextView`的,它添加了文本编辑功能。我们...

    Android EditText 手机号码分段显示

    综上所述,通过结合`EditText`的属性设置、`TextWatcher`监听和自定义格式化方法,我们可以在Android应用中实现手机号码的分段显示功能,为用户提供更好的交互体验。在实际开发中,可以根据具体需求进行定制和扩展,...

    安卓EditText输入框相关-EditText输入电话号码银行卡号自动添加空格分割.zip

    在实际应用中,我们还可能遇到一些额外的需求,例如限制输入长度、不允许输入非数字字符等,这些都可以通过自定义EditText的过滤器(InputFilter)来实现。同时,为了提高用户体验,可以设置监听器监听输入状态,如...

    Android 自定义编辑框

    本示例将探讨如何使用Drawable资源来自定义编辑框(EditText),以实现更个性化的UI效果。 首先,编辑框(EditText)是Android中用于用户输入文本的基本控件,它的外观和行为可以通过XML属性或代码进行定制。在这里...

    android 前面部分可以编辑后面部分不可编辑的EditText Demo.zip

    这在显示预设信息并允许用户在其后添加自定义内容时非常有用,例如电话号码格式化或日期输入。 标题“android 前面部分可以编辑后面部分不可编辑的EditText Demo”所指向的就是这样一个定制的EditText实现。在这样...

    安卓EditText输入框相关-EditText内容分不同块显示支持校验删除块添加块得到块代表的字符串集合.rar

    7. **学习与参考**:尽管这个实现可能无法直接运行,但其代码结构和逻辑对于学习如何自定义EditText的功能是很有价值的。开发者可以通过阅读源码来理解如何扩展EditText的默认行为,以及如何实现复杂的文本处理逻辑...

    android edittext 添加表情

    在Android开发中,EditText是用于用户输入文本的基本控件,但在一些社交应用或者聊天界面中,我们常常需要在EditText中实现表情输入功能,以增强用户的交互体验。本篇将详细介绍如何在Android的EditText中添加表情...

    Android自定义Dialog带分隔的8位输入框按钮回调输入值部分代码

    在Android开发中,自定义Dialog是一种常见的需求,用于提供一种特殊的用户交互方式。在这个场景下,我们想要创建一个带有分隔符的8位输入框的自定义Dialog,并且当用户点击按钮时,能够通过回调方法将输入的值传递到...

    Android应用源码之前面部分可以编辑后面部分不可编辑的EditText.rar

    总的来说,实现"Android应用源码之前面部分可以编辑后面部分不可编辑的EditText"的核心在于自定义EditText控件,通过重写`onTouchEvent()`方法并结合`InputFilter`等手段,控制用户输入的范围和格式。这个压缩包中的...

    Android 手机号自动分割

    在Android开发中,手机号自动分割是一项常见的需求,尤其是在处理用户输入或者进行数据验证时。这个话题涉及到字符串处理、正则表达式以及用户界面设计等多个方面。以下是对这一知识点的详细阐述: 1. **字符串处理...

    Android高级应用源码-前面部分可以编辑后面部分不可编辑的EditText.zip

    1. **创建自定义EditText类**:创建一个新的Java类,继承自EditText,并添加必要的成员变量,如可编辑部分的起始位置、长度等。 2. **重写onDraw()方法**:在这个方法中,你需要根据自定义的需求进行绘制。首先调用...

    android 自定义控件

    本篇文章将深入探讨Android自定义控件的创建过程及其相关知识点。 首先,自定义控件主要分为两类:扩展已有的Android控件(如TextView、Button等)和完全自定义的View。对于扩展已有的控件,我们通常通过继承相应的...

    Android 自定义AlertDialog对话框样式

    在dialog_layout.xml文件中,我们可以定义一个TextView显示wifi名称,一条分割线,一个EditText用于密码输入,以及两个Button用于取消与连接。自定义AlertDialog对话框样式可以满足各种实际的需求。

    Android高级应用源码-前面部分可以编辑后面部分不可编辑的EditText.rar

    1. **自定义EditText子类**: 首先,创建一个新的Java类,继承自EditText。在这个类中,我们需要覆盖`onKey`或`onTextContextMenuItem`等与文本输入相关的事件处理方法,以便对用户的输入行为进行拦截和控制。 2. ...

    EditText输入电话号码、银行卡号自动添加空格分割

    在Android开发中,`EditText` 是一个非常常见的组件,用于接收用户输入文本。在实际应用中,特别是金融或电信类应用,我们常常需要用户输入电话号码或银行卡号。为了提高用户体验和可读性,通常会要求在特定位置(如...

    Android金额输入控件

    在Android中,我们通常使用`EditText`作为用户输入的基础组件。为了限制用户输入,我们可以重写`EditText`的`addTextChangedListener`方法,添加一个监听器来捕获用户输入的每一个字符。在监听器内部,我们可以通过`...

    前面部分可以编辑后面部分不可编辑的EditText

    要实现"前面部分可以编辑后面部分不可编辑"的效果,我们需要对EditText进行扩展,创建一个新的自定义View类。这个类会继承自EditText,并覆盖或扩展其默认行为。 1. **自定义View类**:在Java代码中,我们需要创建...

Global site tag (gtag.js) - Google Analytics