您的位置:首页 > 其它

自定义控件>智能文本框(InputView)

2015-09-19 19:37 351 查看
<span style="font-family:Consolas;color:#ff0000;">拒绝转载,拒绝抄袭,代码虽然写的烂(赶项目),希望还是能帮助到某些人...</span>
<span style="font-family: Consolas; font-size: 10.5pt;">package xx.uicontrol.view;</span>
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Color;
import android.os.Build;
import android.text.Editable;
import android.text.InputType;
import android.text.Selection;
import android.text.TextWatcher;
import android.text.method.DigitsKeyListener;
import android.util.AttributeSet;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.RelativeLayout;
import android.widget.TextView;

import xxx.R;
import xxx.DensityUtils;

/**
 * 文本框控件 on xlzhen 8/15 2015.
 */
public class InputView extends RelativeLayout {
    private TextView left_hint, right_message;//左边的文本提示,右边的输入文本提示
    private EditText editText;//文本框
    private View view_spacing;//顶部的间距线
    private RelativeLayout rela_layout;//包含所有控件的布局文件,可以在里面addView
    private ImageView LeftImageView;

    private String left_hints, right_ok, right_error, right_max, right_min, edit_hint, edit_regex, edit_digits, view_spacing_visibility, left_text_type, edit_type, right_text;
    private int left_img, edit_min, edit_max, right_error_color, edit_height, edit_id;//edit_id 0:默认比较字符串大小 1:比较价格大小 2:银行卡号智能输入
    private boolean edit_singleline;
    public int input_state = 1;//0:可以使用 1:不符合规范 2:字数过少 3:字数过多
    private double edit_bj_max = 0;

    private int margin_top, margin_bottom;

    public InputView(Context context, AttributeSet attrs) {
        super(context, attrs);
        LayoutInflater.from(context).inflate(R.layout.input_edit_layout, this, true);
        initData(context, attrs);
    }

    /*
    *通过attr初始化控件
    *left_hints 文本框左边的描述文本string
    * right_ok 文本框右边的文本提示(输入正确)
    * right_error 文本框右边的文本提示(输入错误,比如不符合规范,一般是跟在正则匹配错误的情况)
    * right_max 文本框右边的文本提示(输入的字数超过长度)
    * right_min 文本框右边的文本提示(输入的字数少于指定的长度)
    * edit_hint 文本框内的文本提示
    * edit_regex 输入文本的正则匹配规则,输入后匹配规则
    * edit_digits 允许输入的字符,输入前就过滤掉其他字符
    * left_text_type 文本框左边的描述文本的左边一个小的提示文本,比如选填,必填,或者*
    * edit_type 文本输入类型,比如只允许输入数值TYPE_CLASS_NUMBER,或者密码TYPE_TEXT_VARIATION_PASSWORD,或者TYPE_CLASS_PHONE 电话号码规则
    * left_offset 文本框左边的描述文本的长度
    * edit_min 文本框内字符长度规范(最小)
    * edit_max 文本框内字符长度规范(最大)
    * edit_id 文本框内字符串输入时给用户看到的规范 0:普通的规范(字符长度匹配),1:数值比较大小(转换成int类型后比较传进来的数值大小),2:银行卡类型,四位一空
    * right_error_color 文本框输入不规范时(不符合规则,过长,过短)文本提示颜色
    * edit_height 文本框长度,默认45*1,xml那边只要输入1即可,需要多行输入的文本框则输入其他值比如2,3,4,5。
    * view_spacing_visibility 控件顶部线条是否隐藏
    * edit_bj_max 文本框内输入的数值和它比较
    * edit_singleline 文本内容是否单行?默认单行
    *
    */
    public void initData(Context context, AttributeSet attrs) {
        rela_layout = (RelativeLayout) findViewById(R.id.rela_layout);

        TypedArray typedArray = getContext().obtainStyledAttributes(attrs,
                R.styleable.InputView);
        /*初始化string*/
        left_hints = typedArray.getString(R.styleable.InputView_left_hint);
        right_ok = typedArray.getString(R.styleable.InputView_right_message);
        right_error = typedArray.getString(R.styleable.InputView_right_error);
        right_max = typedArray.getString(R.styleable.InputView_right_max);
        right_min = typedArray.getString(R.styleable.InputView_right_min);
        edit_hint = typedArray.getString(R.styleable.InputView_edit_hint);
        edit_regex = typedArray.getString(R.styleable.InputView_edit_regex);
        edit_digits = typedArray.getString(R.styleable.InputView_edit_digits);
        left_text_type = typedArray.getString(R.styleable.InputView_left_text_type);
        edit_type = typedArray.getString(R.styleable.InputView_edit_type);
        right_text = typedArray.getString(R.styleable.InputView_right_text);

        /*初始化int*/
        left_img = typedArray.getResourceId(R.styleable.InputView_left_img, R.mipmap.icon5);
        edit_min = typedArray.getInteger(R.styleable.InputView_edit_min, 0);
        edit_max = typedArray.getInteger(R.styleable.InputView_edit_max, 1000);
        edit_id = typedArray.getInt(R.styleable.InputView_edit_id, 0);
        right_error_color = typedArray.getResourceId(R.styleable.InputView_right_error_color, R.color.error);
        edit_height = typedArray.getInt(R.styleable.InputView_edit_height, 1);
        view_spacing_visibility = typedArray.getString(R.styleable.InputView_view_spacing_visibility);
        margin_top = typedArray.getInt(R.styleable.InputView_margin_top, 5);
        margin_bottom = typedArray.getInt(R.styleable.InputView_margin_bottom, 5);

        /*初始化double*/
        edit_bj_max = typedArray.getFloat(R.styleable.InputView_edit_bj_max, 0);

        /*初始化bool*/
        edit_singleline = typedArray.getBoolean(R.styleable.InputView_edit_singleline, true);
        LeftImageView = (ImageView) findViewById(R.id.LeftImageView);
        if (left_img != R.mipmap.icon5)
            LeftImageView.setImageResource(left_img);
        else
            LeftImageView.setVisibility(GONE);

        left_hint = (TextView) findViewById(R.id.left_hint);
        left_hint.setText(left_hints);

        if (left_text_type != null)
            addLeftTextType(getResources().getString(R.string.tongyong_xuantian));
        if (right_text != null)
            addRightTextType(right_text);
        editText = (EditText) findViewById(R.id.editText);
        LayoutParams layoutParams = new LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, DensityUtils.dp2px(edit_height * 42
                , context));
        layoutParams.addRule(RelativeLayout.RIGHT_OF, R.id.left_hint);
        layoutParams.addRule(RelativeLayout.CENTER_VERTICAL);
        layoutParams.setMargins(DensityUtils.dp2px(5, getContext()), DensityUtils.dp2px(margin_top, getContext()), 0, DensityUtils.dp2px(margin_bottom, getContext()));
        editText.setLayoutParams(layoutParams);
        if (edit_hint != null)
            editText.setHint(edit_hint);
        editText.setBackgroundDrawable(null);
        //editText.setBackgroundResource(typedArray.getResourceId(R.styleable.InputView_edit_resources, R.drawable.edit_text_layout));
        if (edit_singleline)
            editText.setSingleLine();

        if (edit_digits != null)
            editText.setKeyListener(DigitsKeyListener.getInstance(edit_digits));

        view_spacing = findViewById(R.id.view_spacing);
        if (view_spacing_visibility != null) {
            switch (view_spacing_visibility) {
                case "VISIBLE"://显示
                    view_spacing.setVisibility(View.VISIBLE);
                    break;
                case "INVISIBLE"://隐藏,不让用户看到,但实际存在在布局内
                    view_spacing.setVisibility(View.INVISIBLE);
                    break;
                case "GONE"://隐藏,布局内不显示
                    view_spacing.setVisibility(View.GONE);
                    break;
            }
        }

        if (edit_type != null) {
            switch (edit_type) {
                case "TYPE_CLASS_NUMBER"://只允许输入数字
                    editText.setInputType(InputType.TYPE_CLASS_NUMBER);
                    break;
                case "TYPE_TEXT_VARIATION_PASSWORD"://只允许输入密码类型
                    editText.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_PASSWORD);
                    break;
                case "TYPE_CLASS_PHONE"://手机号码输入类型
                    editText.setInputType(InputType.TYPE_CLASS_PHONE);
                    break;
            }
        }

        right_message = (TextView) findViewById(R.id.right_message);
        right_message.setTextColor(getResources().getColor(right_error_color));
        if (edit_id == 0)
            initWidget();
        else if (edit_id == 1)
            initWidgetMoney();
        else
            initWidgetId();
    }

    /*
    *初始化文本框的输入监听:数值比较大小
    */
    private void initWidgetMoney() {
        editText.addTextChangedListener(new TextWatcher() {
            @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) {
                try {
                    if (s.toString().length() > 0 && edit_bj_max > 0) {
                        if (Double.parseDouble(s.toString()) > edit_bj_max ) {
                            setRightMeeage(3);
                        } else if (Double.parseDouble(s.toString()) < edit_min) {
                            setRightMeeage(2);
                        } else {
                            setRightMeeage(0);
                        }
                    } else {
                        setRightMeeage(1);
                    }
                } catch (Exception ex) {
                    setRightMeeage(1);
                }

            }
        });
    }

    /*
     *初始化文本框的输入监听:字符串长度比较
     */
    public void initWidget() {
        editText.addTextChangedListener(new TextWatcher() {
            @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 (edit_regex != null && s.toString().matches(edit_regex)) {
                    setEditTextType(s);
                } else if (edit_regex == null) {
                    setEditTextType(s);
                } else {
                    setRightMeeage(1);
                }
            }
        });
    }

    /*
    *银行卡输入类型 四位一空
    */
    public void initWidgetId() {

        editText.setInputType(InputType.TYPE_CLASS_NUMBER);

        editText.addTextChangedListener(new TextWatcher() {
            int beforeTextLength = 0;
            int onTextLength = 0;
            boolean isChanged = false;

            int location = 0;
            private char[] tempChar;
            private StringBuffer buffer = new StringBuffer();
            int konggeNumberB = 0;

            @Override
            public void onTextChanged(CharSequence s, int start, int before, int count) {
                // TODO Auto-generated method stub
                onTextLength = s.length();
                buffer.append(s.toString());
                if (onTextLength == beforeTextLength || onTextLength <= 3 || isChanged) {
                    isChanged = false;
                    return;
                }
                isChanged = true;
            }

            @Override
            public void beforeTextChanged(CharSequence s, int start, int count, int after) {
                // TODO Auto-generated method stub
                beforeTextLength = s.length();
                if (buffer.length() > 0) {
                    buffer.delete(0, buffer.length());
                }
                konggeNumberB = 0;
                for (int i = 0; i < s.length(); i++) {
                    if (s.charAt(i) == ' ') {
                        konggeNumberB++;
                    }
                }
            }

            @Override
            public void afterTextChanged(Editable s) {
                // TODO Auto-generated method stub
                if (isChanged) {
                    location = editText.getSelectionEnd();
                    int index = 0;
                    while (index < buffer.length()) {
                        if (buffer.charAt(index) == ' ') {
                            buffer.deleteCharAt(index);
                        } else {
                            index++;
                        }
                    }

                    index = 0;
                    int konggeNumberC = 0;
                    while (index < buffer.length()) {
                        if (index % 5 == 4) {
                            buffer.insert(index, ' ');
                            konggeNumberC++;
                        }
                        index++;
                    }

                    if (konggeNumberC > konggeNumberB) {
                        location += (konggeNumberC - konggeNumberB);
                    }

                    tempChar = new char[buffer.length()];
                    buffer.getChars(0, buffer.length(), tempChar, 0);
                    String str = buffer.toString();
                    if (location > str.length()) {
                        location = str.length();
                    } else if (location < 0) {
                        location = 0;
                    }

                    editText.setText(str);
                    Editable etable = editText.getText();
                    Selection.setSelection(etable, location);
                    isChanged = false;
                    setEditTextType(s);
                }
            }
        });
    }

    /*
    *根据文本框输入字符判断如何分发事件
    */
    public void setEditTextType(Editable s) {
        if (s.toString().length() < edit_min) {
            setRightMeeage(2);
        } else if (s.toString().length() > edit_max) {
            setRightMeeage(3);
        } else {
            setRightMeeage(0);
        }
    }

    /*
    *传入state状态,使right_message显示不同的内容
    */
    public void setRightMeeage(int input_state) {
        this.input_state = input_state;
        right_message.setVisibility(VISIBLE);
        switch (input_state) {
            case 0://可以使用
                right_message.setText(right_ok);
                right_message.setTextColor(getResources().getColor(R.color.ok));
                right_message.removeCallbacks(runnable);
                right_message.postDelayed(runnable, 2000);
                break;
            case 1://不符合规范
                right_message.setText(right_error);
                right_message.setTextColor(getResources().getColor(right_error_color));
                break;
            case 2://字数过少
                right_message.setText(right_min);
                right_message.setTextColor(getResources().getColor(right_error_color));
                break;
            case 3://字数过多
                right_message.setText(right_max);
                right_message.setTextColor(getResources().getColor(right_error_color));
                break;
        }

    }

    public Runnable runnable = new Runnable() {
        @Override
        public void run() {
            if (InputView.this.input_state == 0)
                right_message.setVisibility(INVISIBLE);//如果是可以使用,那么在延时两秒后,隐藏提示语
        }
    };

    /*
        *左边文本提示的旁边的选填必填或*皆可
        */
    public void addLeftTextType(String text) {
        LeftImageView.setVisibility(GONE);
        LayoutParams layoutParams = new LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
        layoutParams.addRule(RelativeLayout.CENTER_VERTICAL);
        TextView textView = new TextView(getContext());
        textView.setId(R.id.right_message + 1);
        textView.setLayoutParams(layoutParams);
        textView.setPadding(DensityUtils.dp2px(5, getContext()), 0, DensityUtils.dp2px(5, getContext()), 0);
        textView.setGravity(Gravity.RIGHT);
        textView.setTextSize(12f);
        textView.setTextColor(getResources().getColor(R.color.arrow_text));
        textView.setText(text);
        rela_layout.addView(textView);
        layoutParams = new LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
        layoutParams.addRule(RelativeLayout.RIGHT_OF, R.id.right_message + 1);
        layoutParams.addRule(RelativeLayout.CENTER_VERTICAL);
        left_hint.setLayoutParams(layoutParams);
    }

    public void addRightTextType(String text) {
        TextView textView = new TextView(getContext());
        RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
        layoutParams.addRule(RelativeLayout.ALIGN_PARENT_RIGHT);
        layoutParams.addRule(RelativeLayout.CENTER_VERTICAL);
        layoutParams.setMargins(DensityUtils.dp2px(20, getContext()), DensityUtils.dp2px(8.5f, getContext()), DensityUtils.dp2px(20, getContext()), 0);
        textView.setLayoutParams(layoutParams);
        textView.setTextSize(16);
        textView.setTextColor(getResources().getColor(R.color.arrow_text));
        textView.setText(text);
        rela_layout.addView(textView);
    }

    /*
    *取得editale,功能更全
    */
    public Editable getText() {
        return editText.getText();
    }

    /*
    *传值给edittext
    */
    public void setText(String s) {
        editText.setText(s);
        editText.setSelection(s != null ? s.length() : 0);
    }

    /*
    *取得string值
    */
    public String getTextToString() {
        return editText.getText().toString();
    }

    /*
    *取得edittext
    */
    public EditText getEditText() {
        return editText;
    }

    /*
    * 取得input_state状态
    */
    public int getInputOks() {
        return input_state;
    }

    /*
    *清空文本框内容
    */
    public void setEditTextClear() {
        editText.setText("");
        right_message.setText("");
    }
    public void setRightMessageClear(){
        right_message.setText("");
    }
    /*
    *给文本框传入值后禁止文本框再输入内容
    */
    public void setStopInput(String nums) {
        editText.setText(nums);
        editText.setFocusable(false);
        editText.setKeyListener(null);
    }

    /*
    *禁止文本框输入内容
    */
    public void setStopInput() {
        editText.setFocusable(false);
        editText.setKeyListener(null);
    }

    /*
    *禁止文本框输入内容,点击文本框时传入click事件
    */
    public void setStopInput(OnClickListener onClick) {
        editText.setFocusable(false);
        editText.setClickable(true);
        editText.setOnClickListener(onClick);
    }

    /*
    *文本框的数值动态传入。
    */
    public void setMaxLenght(String edit_max, String left_message, String right_message) {
        edit_bj_max = Double.parseDouble(edit_max);
        right_max = left_message + edit_max + right_message;
        editText.setText("");
    }
}

以下是依赖的xml界面文件。
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/rela_layout"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:background="@color/white">
    <View
        android:id="@+id/view_spacing"
        android:layout_width="match_parent"
        android:layout_height="0.5dp"
        android:background="@color/input_bottom_jianju"/>
    <ImageView
        android:id="@+id/LeftImageView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginLeft="16dp"
        android:layout_centerVertical="true"/>
    <TextView
        android:id="@+id/left_hint"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginLeft="10dp"
        android:layout_toRightOf="@+id/LeftImageView"
        android:textColor="@color/arrow_text"
        android:textSize="@dimen/text_big_middle_size"
        android:layout_centerVertical="true"/>
    <EditText
        android:id="@+id/editText"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:textSize="@dimen/text_big_middle_size"
        android:gravity="center_vertical"
        android:layout_centerVertical="true"
        android:background="@drawable/edit_text_layout"/>
    <TextView
        android:id="@+id/right_message"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textSize="12sp"
        android:layout_marginRight="10dp"
        android:layout_marginTop="2dp"
        android:layout_alignParentRight="true"
        android:layout_alignBottom="@+id/editText"/>
</RelativeLayout>
//以下是使用方法
<xxx.InputView
                android:id="@+id/edit_bank_card"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_below="@+id/bank_person_name"
                app:edit_id="2"
                app:edit_max="23"
                app:edit_min="19"
                app:edit_digits="0123456789"
                app:left_hint="@string/setting_bankcard_text"
                app:right_error="输入不正确"
                app:right_min="少于标准的16位"
                app:right_max="多于标准的19位"
                app:right_message="@string/message_ok_lenght"
                app:edit_hint="请输入卡号"
                app:left_img="@mipmap/name_myaccount"/>


内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: