您的位置:首页 > 移动开发 > Android开发

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

2014-06-03 14:53 891 查看
例如,输入一组25位的序列号,希望分成5组,每组5个数字。效果如下图。 


 

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

1.首先自定义控件继承EditText,实现相应方法。 

Java代码  



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代码  



<?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代码  



<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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息