自定義EditText實現IP輸入框

你們聽說過需要在Andrid設備上輸入IP地址的需求嗎,不管你們聽說了沒有,反正我是沒聽說。這不,產品提出了這麼逆天的需求。

祖傳的圖,傳男不傳女。
這裏寫圖片描述

爲了點擊鍵盤效果明顯,特地下載一款這麼風騷的皮膚。

先說下大致思路

  1. 繼承LinearLayout
  2. 實現了多個EditText橫向排列。
  3. 去掉每個EditText的背景
  4. Linearlayout中onDraw()方法繪製邊框
  5. 爲每個EditText添加輸入監聽

解說一下越到坑

1. LinearLayout的onDraw方法需要執行,需要添加下面代碼
 setDividerDrawable(getResources().getDrawable(android.R.drawable.divider_horizontal_textfield));
2. 每個EditText輸入完畢,如何讓下一個EditText選中,
3. 當一個EditText刪除完畢,如何讓上一個EditText被選中
4. **未解決的BUG,現在每個EditText的長度必須是3,才能完美的焦點切換**

下面貼一下代碼

**
 * Created by xiongchengguang on 2016/12/22.
 */

public class SuperEditText extends LinearLayout implements TextWatcher {
    private static final String TAG = "IPEditText";

    private int width;
    private int height;
    private Paint paint;

    private static final int DEFAULT_TEXT_MAX_LENGTH = 3;
    private static final int DEFAULT_TEXT_SIZE = 16;
    private static final int DEFAULT_TEXT_COLOR = Color.BLACK;
    private static final int DEFAULT_BORDER_COLOR = Color.BLACK;
    private static final int DEFAULT_BORDER_WIDTH = 2;
    private static final int DEFAULT_POINT_COLOR = Color.BLACK;
    private static final int DEFAULT_POINT_WIDTH = 5;
    private static final int DEFAULT_IP_EDITTEXT_LENGTH = 4;

    private int textLength;
    private int textSize;
    private int textColor;

    private int borderColor;
    private int borderWidth;

    private int pointColor;
    private int pointWidth;
    private int editNumber;


    private int default_height = px2dp(20);
    private int default_width = px2dp(60);

    private List<EditText> data = new ArrayList<>();

    public SuperEditText(Context context) {
        this(context, null);
    }

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

    public SuperEditText(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.SuperEditText, defStyleAttr, 0);
        textLength = ta.getInt(R.styleable.SuperEditText_textLength, DEFAULT_TEXT_MAX_LENGTH);

        textSize = (int) ta.getDimension(R.styleable.SuperEditText_textSize, DEFAULT_TEXT_SIZE);
        textColor = ta.getColor(R.styleable.SuperEditText_textColor, DEFAULT_TEXT_COLOR);

        borderColor = ta.getColor(R.styleable.SuperEditText_borderColor, DEFAULT_BORDER_COLOR);
        borderWidth = (int) ta.getDimension(R.styleable.SuperEditText_borderWidth, DEFAULT_BORDER_WIDTH);

        pointColor = ta.getColor(R.styleable.SuperEditText_pointColor, DEFAULT_POINT_COLOR);
        pointWidth = (int) ta.getDimension(R.styleable.SuperEditText_pointWidth, DEFAULT_POINT_WIDTH);

        editNumber = ta.getInt(R.styleable.SuperEditText_editNumber, DEFAULT_IP_EDITTEXT_LENGTH);

        init(context);
        initPaint();
    }

    public float getTextSize() {
        return data.get(0).getTextSize();
    }

    private void initPaint() {
        paint = new Paint();
        paint.setAntiAlias(true);
        paint.setStrokeWidth(2);
        paint.setStyle(Paint.Style.FILL);
    }


    private void init(Context context) {
        for (int i = 0; i < editNumber; i++) {
            EditText edit = new EditText(context);
            edit.setBackground(null);
            edit.setFilters(new InputFilter[]{new InputFilter.LengthFilter(textLength)});
            edit.setTextSize(textSize);
            edit.setTextColor(textColor);
            edit.setGravity(Gravity.CENTER);
            edit.setInputType(InputType.TYPE_CLASS_NUMBER);
            edit.setMinHeight(default_height);
            edit.setMinWidth(default_width);
            edit.setTag(i);
            edit.setMaxLines(1);
            edit.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT, 1));
            edit.addTextChangedListener(this);
            addView(edit);
            data.add(edit);
        }

        setDividerDrawable(getResources().getDrawable(android.R.drawable.divider_horizontal_textfield));
        setOrientation(LinearLayout.HORIZONTAL);
    }


    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        int l = data.get(0).getLeft();
        int t = data.get(0).getTop() - getPaddingTop();
        int r = width - getPaddingRight();
        int b = height;

        Rect rect = new Rect(l, t, r, b);

        paint.setColor(borderColor);
        paint.setStrokeWidth(borderWidth);
        paint.setStyle(Paint.Style.STROKE);
        canvas.drawRect(rect, paint);

        int y = height / 2;
        int x = width / editNumber;
        paint.setStrokeWidth(pointWidth);
        paint.setColor(pointColor);
        for (int i = 1; i < data.size(); i++) {
            canvas.drawPoint(x * i, y, paint);
        }
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        width = w;
        height = h;
    }

    @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 (listener != null) {
            listener.afterTextChanged(getSuperEditTextValue());
        }
        if (s.length() == 3) {
            for (int i = 0; i < data.size(); i++) {
                EditText edit = data.get(i);
                String val = edit.getText().toString();
                if (val.length() == 0) {
                    edit.requestFocus();
                    return;
                }
            }
        } else if (s.length() == 0) {
            for (int i = data.size() - 1; i >= 0; i--) {
                EditText edit = data.get(i);
                edit.setFocusable(true);
                String val = edit.getText().toString();
                if (val.length() == 3) {
                    edit.requestFocus();
                    edit.setSelection(3);
                    return;
                }
            }
        }
    }

    public String[] getSuperEditTextValue() {
        String[] val = new String[editNumber];
        for (int i = 0; i < editNumber; i++) {
            val[i] = data.get(i).getText().toString();
            KLog.d(data.get(i).getText().toString());
        }
        return val;
    }

    public void setSuperEdittextValue(String[] s) {
        for (int i = 0; i < s.length; i++) {
            data.get(i).setText(s[i]);
        }
    }

    public boolean getSuperCompile() {
        for (int i = 0; i < editNumber; i++) {
            String str = data.get(i).getText().toString();
            if (Integer.parseInt(str) <= 255) {
                return true;
            }
        }
        return false;
    }

    public int px2dp(int val) {
        return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, val, getResources().getDisplayMetrics());
    }

    public int px2sp(int val) {
        return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, val, getResources().getDisplayMetrics());
    }

    public interface SuperTextWatcher {
        public void afterTextChanged(String[] s);
    }

    private SuperTextWatcher listener;

    public void setSuperTextWatcher(SuperTextWatcher listener) {
        this.listener = listener;
    }

}

自定義屬性的

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <declare-styleable name="SuperEditText">
        <attr name="textLength" format="integer" />
        <attr name="textSize" format="dimension" />
        <attr name="textColor" format="color" />

        <attr name="borderColor" format="color" />
        <attr name="borderWidth" format="dimension" />
        <attr name="pointColor" format="color" />
        <attr name="pointWidth" format="dimension" />

        <attr name="editNumber" format="integer" />

    </declare-styleable>
</resources>

歡迎各位老司機前來帶路

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章