Android 自定义控件 IPEditText

2022-06-14  本文已影响0人  sssssss_

自定义的IP输入框

参考自:https://github.com/lanyan520/Idea-EditText

功能分析

  1. 四个输入框;
  2. 输入框最多输入3位数,且不能大于255;
  3. 不满足条件2的时候,自动切换到下一个输入框;
  4. get方法能快速获取IP地址

  1. AbsEditText
  2. AbsEditTextGroup
  3. IPEditText
  4. IPView

使用

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <com.zhd.screenviewer.ipview.IPView
        android:id="@+id/ip_view"
        android:layout_width="match_parent"
        android:layout_height="40dp"
        android:layout_margin="10dp" />

</LinearLayout>

代码

1. AbsEditText

import android.content.Context;
import android.text.InputFilter;
import android.text.method.NumberKeyListener;
import android.util.AttributeSet;


public abstract class AbsEditText extends androidx.appcompat.widget.AppCompatEditText {
    public AbsEditText(Context context) {
        this(context, null, 0);
    }

    public AbsEditText(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public AbsEditText(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        setMaxLength();
        addInputFilter();
    }

    /**
     * 初始化配置
     */
    protected void setMaxLength() {
        //setOnKeyListener((OnKeyListener) DigitsKeyListener.getInstance(""));
        setFilters(new InputFilter[]{ new InputFilter.LengthFilter(getMaxLength()) });
    }

    protected void addInputFilter() {
        setKeyListener(new NumberKeyListener() {
            @Override
            protected char[] getAcceptedChars() {
                return getInputFilterAcceptedChars();
            }

            @Override
            public int getInputType() {
                return getEditTextInputType();
            }
        });
    }

    /**
     * 输入内容最大长度
     * @return
     */
    public abstract int getMaxLength();

    /**
     * 输入内容过滤
     * @return
     */
    public abstract char[] getInputFilterAcceptedChars();

    /**
     * 输入内容检查是否ok
     * @return
     */
    public abstract boolean checkInputValue();

    public abstract int getEditTextInputType();
    
}

2. AbsEditTextGroup


import java.util.ArrayList;

import android.content.Context;
import android.graphics.drawable.ColorDrawable;
import android.text.Editable;
import android.text.TextWatcher;
import android.util.AttributeSet;
import android.view.Gravity;
import android.view.KeyEvent;
import android.view.View;
import android.widget.LinearLayout;
import android.widget.TextView;


public abstract class AbsEditTextGroup extends LinearLayout implements TextWatcher {

    protected float sp16 = 16.0f;
    protected int dp4 = 4;
    protected ArrayList<AbsEditText> editTexts = new ArrayList<AbsEditText>();

    public AbsEditTextGroup(Context context) {
        this(context, null, 0);
    }

    public AbsEditTextGroup(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public AbsEditTextGroup(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        addViews();
        buildListener();
    }


    protected void addViews() {
        for (int i = 0; i < getChildCount(); i++) {
            if (i % 2 == 0) {
                AbsEditText absEditText = createAbsEditText();
                editTexts.add(absEditText);
                addView(absEditText);
            } else {
                addView(createSemicolonTextView());
            }
        }
    }

    protected AbsEditText createAbsEditText() {

        AbsEditText absEditText = getAbsEditText();
        LayoutParams params = new LayoutParams(0, LayoutParams.MATCH_PARENT);
        params.weight = 1;
        absEditText.setLayoutParams(params);
        absEditText.setTextSize(sp16);//sp
        absEditText.setTextColor(0xFF888888);
        absEditText.setGravity(Gravity.CENTER);
        absEditText.setPadding(dp4, dp4, dp4, dp4);
        absEditText.setSingleLine();
        absEditText.setHint("0");
        absEditText.setFocusableInTouchMode(true);
        absEditText.setBackgroundDrawable(new ColorDrawable(0xFFFFFFFF));
        applyEditTextTheme(absEditText);
        return absEditText;
    }

    protected TextView createSemicolonTextView() {
        TextView textView = new TextView(getContext());
        LayoutParams params = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.MATCH_PARENT);
        textView.setLayoutParams(params);
        textView.setTextSize(sp16);//sp
        textView.setTextColor(0xFF444444);
        textView.setText(getSemicolomText());
        applySemicolonTextViewTheme(textView);
        return textView;
    }

    protected void buildListener() {
        for (int i = 0; i < editTexts.size(); i++) {
            editTexts.get(i).addTextChangedListener(this);
            if (i != 0) {
                editTexts.get(i).setOnKeyListener(new OnDelKeyListener(editTexts.get(i - 1), editTexts.get(i)));
            }
        }
    }

    @Override
    public void beforeTextChanged(CharSequence s, int start, int count, int after) {

    }

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

    }

    @Override
    public void afterTextChanged(Editable s) {
        if (s.toString().length() == getDelMaxLength()) {
            for (int i = 0; i < editTexts.size() - 1; i++) {
                if (editTexts.get(i).hasFocus()) { //hasFocus √ & isFocus ×
                    editTexts.get(i).clearFocus();
                    editTexts.get(i + 1).requestFocus();
                    break;
                }
            }
        }
    }

    public boolean checkInputValue() {
        boolean result = true;
        for (int i = 0; i < editTexts.size(); i++) {
            if (!editTexts.get(i).checkInputValue()) {
                result = false;
                break;
            }
        }

        return result;
    }

    /**
     * IP网关子网掩码转byte4个字节
     * @return
     */
    public byte[] getBytesWithIP() {
        byte[] result = new byte[4];
        for (int i = 0; i < editTexts.size(); i++) {
            int number = Integer.valueOf(editTexts.get(i).getText().toString());
            result[i] = (byte) number;
        }
        return result;
    }

    /**
     * Mac地址转换6字节byte
     * @return
     */
    public byte[] getBytesWithMac() {
        byte[] result = new byte[6];
        for (int i = 0; i < editTexts.size(); i++) {
            String mac = editTexts.get(i).getText().toString();
            byte byteMac = Integer.valueOf(mac, 16).byteValue();
            result[i] = byteMac;
        }
        return result;
    }


    /**
     * 重置自布局的输入控件
     */
    public void resetText() {
        for (AbsEditText editText : editTexts) {
            editText.setText("");
        }
    }

    class OnDelKeyListener implements OnKeyListener {

        private AbsEditText clearEditText;
        private AbsEditText requestEditText;

        public OnDelKeyListener(AbsEditText requestEditText, AbsEditText clearEditText) {
            this.requestEditText = requestEditText;
            this.clearEditText = clearEditText;
        }

        @Override
        public boolean onKey(View v, int keyCode, KeyEvent event) {
            if (keyCode == KeyEvent.KEYCODE_DEL
                    && event.getAction() == KeyEvent.ACTION_DOWN && clearEditText.getSelectionStart() == 0) {
                clearEditText.clearFocus();
                requestEditText.requestFocus();
                requestEditText.setSelection(requestEditText.getText().toString().trim().length());
                return true;
            }
            return false;
        }
    }

    public ArrayList<AbsEditText> getChildEditTextViews() {
        return editTexts;
    }

    public abstract int getChildCount();

    public abstract AbsEditText getAbsEditText();

    public abstract String getSemicolomText();

    public abstract int getDelMaxLength();

    public abstract void applySemicolonTextViewTheme(TextView semicolonTextView);

    public abstract void applyEditTextTheme(AbsEditText absEditText);
}

3. IPEditText

import android.content.Context;
import android.text.InputType;
import android.util.AttributeSet;


public class IPEditText extends AbsEditText {

    public IPEditText(Context context) {
        this(context, null, 0);
    }

    public IPEditText(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public IPEditText(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    @Override
    public int getMaxLength() {
        return 3;
    }

    @Override
    public char[] getInputFilterAcceptedChars() {
        return new char[]{ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' };
    }

    @Override
    public boolean checkInputValue() {
        String textValue = getText().toString().trim();
        if (textValue.isEmpty()) {
            return false;
        } else {
            int number = Integer.valueOf(textValue);
            return number >= 0 && number <= 255;
        }
    }

    @Override
    public int getEditTextInputType() {
        return InputType.TYPE_CLASS_NUMBER;
    }
}

4. IPView

import android.content.Context;
import android.text.Editable;
import android.util.AttributeSet;
import android.view.Gravity;
import android.widget.TextView;


public class IPView extends AbsEditTextGroup {
    public IPView(Context context) {
        this(context, null, 0);
    }

    public IPView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public IPView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    @Override
    public int getChildCount() {
        return 7;
    }

    @Override
    public AbsEditText getAbsEditText() {
        return new IPEditText(getContext());
    }

    @Override
    public String getSemicolomText() {
        return ".";
    }

    @Override
    public int getDelMaxLength() {
        return 3;
    }

    @Override
    public void applySemicolonTextViewTheme(TextView semicolonTextView) {
        semicolonTextView.setPadding(0, 0, 0, 5);
        semicolonTextView.getPaint().setFakeBoldText(true);
        semicolonTextView.setBackgroundColor(0xFFFFFFFF);
        semicolonTextView.setGravity(Gravity.BOTTOM);
    }

    @Override
    public void applyEditTextTheme(AbsEditText absEditText) {

    }

    @Override
    public void afterTextChanged(Editable s) {
        if (s.toString().length() == getDelMaxLength()) {
            for (int i = 0; i < editTexts.size() - 1; i++) {
                if (editTexts.get(i).hasFocus()) { //hasFocus √ & isFocus ×
                    editTexts.get(i).clearFocus();
                    editTexts.get(i + 1).requestFocus();

                    String lastEditTextValue = editTexts.get(i).getText().toString();
                    if (Integer.parseInt(lastEditTextValue) > 255) {
                        editTexts.get(i).setText(lastEditTextValue.substring(0, 2));
                        editTexts.get(i + 1).setText(lastEditTextValue.substring(2, 3));
                        editTexts.get(i + 1).setSelection(1);
                    }
                    break;
                }
            }
        }
    }

    /**
     * 设置初始值,例如默认网关:"255\\.255\\.255\\.0" 正则表达式转义字符相关知识
     */
    public void setGatewayText(String[] ips) {
        if (ips == null) {
            ips = new String[]{ "255", "255", "255", "0" };
        }
        for (int i = 0; i < editTexts.size(); i++) {
            editTexts.get(i).setText(ips[i]);
        }
    }
}
上一篇下一篇

猜你喜欢

热点阅读