自定义控件>智能文本框(InputView)
2015-09-19 19:37
351 查看
以下是依赖的xml界面文件。<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 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"/>