EditText a way to detect IP address input box legality of real-time

2019-08-13

Keywords: EditText, Custom View, real-time detection IP address


 

In doing APK development time, sometimes you encountered to enter the IP address, but the IP address is a certain rule, but they did not provide official Android dedicated to the IP address input box. It is usually the easiest time-saving approach is to provide a direct EditText for user input, and so after a user submits go check rules. Some students also do not want to so casually, they may have their own development or to the Internet to find relevant open source code. I bored out yesterday, also made an IP address input box control, we will now open it out to give newcomers bring some help.

 

The author of this IP address input box control is very simple, it is directly inherited from the official added EditText control and related processing logic implementation. It has the following characteristics:

1, and are consistent in appearance EditText control use;

2, along with real-time detection input character input based on IPv4 rules;

3. The IPv4 rules, data are displayed in different states distinguish between different forms;

4, the source code is extremely lightweight.

 

Use Display

 

 

 

The author of this input box and did not do very strict limitations on the input character, the fact that it allows you to enter any character, but for those non-IP address of the character, it will be grayed out. Did it really take into account the possibility that some scenes will display the IP address the needs of non-character, you do not want to restrict too died.

 

Character input, in line with standard IP address will be displayed in green; the text likely to meet, places orange display; non-compliant, is displayed in red.

 

Is also very simple in use, can be introduced in the following format directly on the layout need to use:

<com.my.pkg.IPEditText
    android:id="@+id/iv01"
    android:layout_centerInParent="true"
    android:inputType="text|number"
    android:layout_width="300dp"
    android:layout_height="50dp" />

可以说和官方的 EditText 完全没有区别了。

 

源码浅析

 

笔者的这个IP地址输入框控件命名为 IPEditText。它仅一份三百多行的 Java 代码,没有额外的文件。它大致的流程如下图所示

关于构造器

构造器虽然有两个,但实际上笔者只实现了在 XML 中使用的构造方法

    public IPEditText(Context context) {
        super(context);
        log("IPEditText(context)");
    }

    public IPEditText(Context context, AttributeSet attrs) {
        super(context, attrs);
        log("IPEditText(context,attrs)");
        super.addTextChangedListener(this);

        textInitialization();
    }

在构造中注册了文本改变的监听器,并且拦截了外部监听注册请求

    @Override
    public void addTextChangedListener(TextWatcher watcher) {
        log("we ignore your call");
    }

 

关于IP规则检查

IPv4 规则的检查功能全部封装在内部类 IPChecker 中。检查会将IP地址分成 4 个字段逐一检查。每个IP字段又被抽象成 IPs 类,IPs 类就包括了当前字段的状态,是正确还是未知还是错误。同时类里面还有两个 StringBuilder 对象,它们在默认情况下是 null 的。只有在检查到当前IP字段的值有错时,才会去实例化对应的 StringBuilder 类对象,这些错误不同类型的信息会被记录到这些 StringBuilder 对象中。

 

完整的 IPEditText 源码如下所示

package com.my.pkg;

import android.content.Context;
import android.text.Editable;
import android.text.Html;
import android.text.TextWatcher;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
import android.widget.EditText;

public class IPEditText extends EditText implements TextWatcher {

    private static final String TAG = "IPEditText";

//    private static final String COLOR_CORRECT = "";
//    private static final String COLOR_WARN = "";
//    private static final String COLOR_ERROR = "";

    private boolean isNeed2Update;
    /**
     * 编辑前的光标。
     * */
    private int oldPos;
    /**
     * 编辑前的字符长度。
     * */
    private int oldLength;

    private View bg;
    private IPChecker ipChecker;

    public IPEditText(Context context) {
        super(context);
        log("IPEditText(context)");
    }

    public IPEditText(Context context, AttributeSet attrs) {
        super(context, attrs);
        log("IPEditText(context,attrs)");
        super.addTextChangedListener(this);

        textInitialization();
    }

    private void textInitialization(){
        ipChecker = new IPChecker();

        //get text.
        String txt = getText().toString();
        log("txt null?" + (txt==null) + ",txt:" + txt);

        //check whether ip string.
        if (txt != null && !"".equals(txt)) {
            ipChecker.check(txt);
            setText(Html.fromHtml(ipChecker.toString()));
            setSelection(getText().length());
        }
        log("getNormalText:" + ipChecker.getNormalTxt());
    }

    private void notifyUpdate(String txt){
        isNeed2Update = false;
        if (txt != null && !"".equals(txt)) {
            ipChecker.check(txt);
            setText(Html.fromHtml(ipChecker.toString()));
            if(getText().length() > oldLength){
                setSelection(oldPos + 1);
            }else{
                setSelection(oldPos);
            }
        }
    }

    @Override
    public void addTextChangedListener(TextWatcher watcher) {
        log("we ignore your call");
    }

    private void log(String msg){
        Log.d(TAG, msg);
    }

    @Override
    public void beforeTextChanged(CharSequence s, int start, int count, int after) {
        if(isNeed2Update){
            oldPos = start;
            oldLength = s.length();
        }
//        log("isNeed:" + isNeed2Update + ",start:" + start + ",length:" + s.length() + ",after:" + after);
    }

    @Override
    public void onTextChanged(CharSequence s, int start, int before, int count) {

    }

    @Override
    public void afterTextChanged(Editable s) {
        if(isNeed2Update){
            notifyUpdate(s.toString());
        }else{
            isNeed2Update = true;
            log("after " + s.toString());
        }
    }

    private class IPChecker {

        /**ipv4*/
        IPs[] ips = new IPs[4];
        /**记录当前检查到哪一IP段落了*/
        int checkingIdx;
        /**记录小数点的数量。*/
        int pointCounter;

        void check(String txt){
            IPEditText.this.log("checking:" + txt);

            // reset environment.
            checkingIdx = 0;
            pointCounter = 0;
            ips[0] = null;
            ips[1] = null;
            ips[2] = null;
            ips[3] = null;

            if (txt == null || "".equals(txt)) {
                return;
            }

            char a[] = txt.toCharArray();
            int idx = 0;
            for(int i = 0; i < a.length; i++){
                if(isNumber(a[i])){
                    if (ips[checkingIdx] == null) {
                        ips[checkingIdx] = new IPs();
                    }

                    //over length.
                    if(ips[checkingIdx].insertIdx >= 3){
                        ips[checkingIdx].initVariableArray();
                        ips[checkingIdx].sb.append(a[i]);
                        ips[checkingIdx].status = ips[checkingIdx].STATUS_ERROR;

                        continue;
                    }

                    ips[checkingIdx].number[ips[checkingIdx].insertIdx++] = a[i];
                    int c = Integer.valueOf(new String(ips[checkingIdx].number, 0, ips[checkingIdx].insertIdx));
                    if(c < 0 || c > 255){
                        ips[checkingIdx].status = ips[checkingIdx].STATUS_ERROR;
                    }else{
                        if(checkingIdx == 3){
                            ips[checkingIdx].status = ips[checkingIdx].STATUS_CORRECT;
                        }else if(checkingIdx > 3){

                        }else{
                            ips[checkingIdx].status = ips[checkingIdx].STATUS_WARN;
                        }
                    }
                }else{
                    if('.' != a[i]){
                        // Error string...
                        IPEditText.this.log("character is not number.");
                        if(ips[checkingIdx] == null){
                            ips[checkingIdx] = new IPs();
                        }

                        ips[checkingIdx].initInvalidCharacterArray();
                        ips[checkingIdx].sbInvalid.append(new String(a, i, a.length - i));

                        break;
                    }

                    if(ips[checkingIdx] == null){
                        // '.' as header.

                        ips[checkingIdx] = new IPs();
                        ips[checkingIdx].initInvalidCharacterArray();
                        ips[checkingIdx].sbInvalid.append(new String(a, i, a.length - i));

                        break;
                    }

                    // check current ip part.
                    if(ips[checkingIdx].status == 1){
                        ips[checkingIdx].status = ips[checkingIdx].STATUS_CORRECT;
                    }

                    // record it.
                    pointCounter++;

                    // upgrade~
                    checkingIdx++;
                }
            }// for -- end.

            //traversal ips
            for(IPs i:ips){
                if (i != null) {
                    String jkl = new String(i.number, 0, i.insertIdx);
                    if("---".equals(jkl)){
                        jkl = i.sb.toString();
                    }
                    IPEditText.this.log(jkl + ",status:" + i.status);
                }
            }
        }

        boolean isNumber(char c){
            IPEditText.this.log("checking character:" + c);
            if('0' <= c && c <= '9') {
                return true;
            }
            return false;
        }

        CharSequence getRichTxt(){
            StringBuilder sb = new StringBuilder();
            int point = pointCounter;
            for(IPs i:ips){
                if (i == null) {
                    break;
                }

                if(i.isCharacterInvalid){
                    sb.append("<font color='#A8A8A8'>");
                    sb.append(i.sbInvalid.toString());
                    sb.append("</font>");

                    continue;
                }

                String tmp = new String(i.number, 0, i.insertIdx);
                if("---".equals(tmp)){
                    tmp = i.sb.toString();
                }

                if(i.status == i.STATUS_CORRECT){
                    sb.append("<font color='#008b00'>");
                }else if(i.status == i.STATUS_WARN){
                    sb.append("<font color='#FFA500'>");
                }else if(i.status == i.STATUS_ERROR){
                    sb.append("<font color='#ff0000'>");
                }else{
                    //...
                }

                sb.append(tmp);
                sb.append("</font>");

                if(point > 0){
                    sb.append('.');
                    point--;
                }
            }

            return sb.toString();
        }

        CharSequence getNormalTxt(){
            StringBuilder sb = new StringBuilder();
            int point = pointCounter;
            for(IPs i:ips){
                if (i == null) {
                    break;
                }

                if(i.isCharacterInvalid){
                    sb.append(i.sbInvalid.toString());

                    continue;
                }

                String tmp = new String(i.number, 0, i.insertIdx);
                if("---".equals(tmp)){
                    tmp = i.sb.toString();
                }
                sb.append(tmp);
                if(point > 0){
                    sb.append('.');
                    point--;
                }
            }

            return sb.toString();
        }

        @Override
        public String toString() {
            return getRichTxt().toString();
        }

        private class IPs {

            final int STATUS_CORRECT = 0;
            final int STATUS_WARN = 1;
            final int STATUS_ERROR = 2;

            char[] number = new char[3];
            int insertIdx;
            /**
             * 0 -- correct
             * 1 -- warn
             * 2 -- error
             * */
            int status;
            /**
             * 当这个值为 true,所有内容都记录到 sbInvalid 中,
             * number[], sb 都没有内容。
             * */
            boolean isCharacterInvalid;

            StringBuilder sb;
            StringBuilder sbInvalid;

            IPs(){
                number[0] = 0;
                number[1] = 0;
                number[2] = 0;
            }

            void initVariableArray(){
                if (sb != null) {
                    return;
                }

                sb = new StringBuilder();

                // append old data.
                for(int i = 0; i < insertIdx; i++){
                    sb.append(number[i]);
                }

                // indicator
                number[0] = '-';
                number[1] = '-';
                number[2] = '-';
                insertIdx = 3;
            }

            void initInvalidCharacterArray(){
                if (sbInvalid != null) {
                    return;
                }

                sbInvalid = new StringBuilder();
                String tmp = new String(number, 0, insertIdx);
                if("---".equals(tmp)){
                    tmp = sb.toString();
                }
                number[0] = 0;
                number[1] = 0;
                number[2] = 0;
                insertIdx = 0;

                sb = null;

                status = STATUS_ERROR;

                sbInvalid.append(tmp);

                isCharacterInvalid = true;
            }
        }
    }
}
View Code

 

 


 

Guess you like

Origin www.cnblogs.com/chorm590/p/11308125.html