Android 带分隔符的EditText

来源:互联网 发布:spark mongodb python 编辑:程序博客网 时间:2024/05/16 12:24

先看效果图,这个也是从网上来的demo  但是是5.0的  我对这个不太熟悉,所以就把代码提出来了。。。


直接来源码了:

package com.z.customedittext;import android.app.Activity;import android.os.Bundle;import android.text.Editable;import android.view.View;import android.widget.Button;import android.widget.TextView;public class MainActivity extends Activity {private XEditText defaultSeparatorEdit;private XEditText customSeparatorEdit;private XEditText showSeparatorEdit;private XEditText customMarkerEdit1;private TextView textView1, textView2;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);defaultSeparatorEdit = (XEditText) findViewById(R.id.default_edit_text);customSeparatorEdit = (XEditText) findViewById(R.id.custom_edit_text);showSeparatorEdit = (XEditText) findViewById(R.id.show_separator_edit_text);customMarkerEdit1 = (XEditText) findViewById(R.id.custom_marker_edit_text1);textView1 = (TextView) findViewById(R.id.text1);textView2 = (TextView) findViewById(R.id.text2);Button button = (Button) findViewById(R.id.show_pattern_btn);customSeparatorEdit.setPattern(new int[] { 4, 4, 4, 4, 4 });customSeparatorEdit.setSeparator("-");defaultSeparatorEdit.setOnTextChangeListener(new XEditText.OnTextChangeListener() {@Overridepublic void beforeTextChanged(CharSequence s, int start, int count, int after) {}@Overridepublic void onTextChanged(CharSequence s, int start, int before, int count) {}@Overridepublic void afterTextChanged(Editable s) {textView1.setText(defaultSeparatorEdit.getNonSeparatorText());}});customSeparatorEdit.setOnTextChangeListener(new XEditText.OnTextChangeListener() {@Overridepublic void beforeTextChanged(CharSequence s, int start, int count, int after) {}@Overridepublic void onTextChanged(CharSequence s, int start, int before, int count) {}@Overridepublic void afterTextChanged(Editable s) {textView2.setText(customSeparatorEdit.getNonSeparatorText());}});button.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {showSeparatorEdit.setTextToSeparate("13800000000");}});customMarkerEdit1.setCustomizeMarkerEnable(true);customMarkerEdit1.setOnMarkerClickListener(new XEditText.OnMarkerClickListener() {@Overridepublic void onMarkerClick(float x, float y) {new MarkerPopWindow(MainActivity.this, customMarkerEdit1, (int) x, (int) y);}});}}

view :

package com.z.customedittext;import android.content.Context;import android.content.res.TypedArray;import android.graphics.Bitmap;import android.graphics.Canvas;import android.graphics.Paint;import android.graphics.Rect;import android.graphics.drawable.BitmapDrawable;import android.graphics.drawable.Drawable;import android.text.Editable;import android.text.InputType;import android.text.TextWatcher;import android.util.AttributeSet;import android.view.MotionEvent;import android.view.View;import android.widget.EditText;/** * 可按自己想要的格式自动分割显示的EditText 默认手机格式:xxx xxxx xxxx * 也可自定义任意格式,如信用卡格式:xxxx-xxxx-xxxx-xxxx 或 xxxx xxxx xxxx xxxx * 使用pattern时无需在xml中设置maxLength属性,若需要设置时应注意加上分隔符的数量  * com.z.customedittext.XEditText * ContentSeparatorEditText */public class XEditText extends EditText {private static final String SPACE = " ";private static final int[] DEFAULT_PATTERN = new int[] { 3, 4, 4 };private OnTextChangeListener mTextChangeListener;private OnMarkerClickListener mMarkerClickListener;private TextWatcher mTextWatcher;private int preLength;private int currLength;private Drawable mRightMarkerDrawable;private Drawable mLeftDrawable;private boolean hasFocused;private int[] pattern; // 模板private int[] intervals; // 根据模板控制分隔符的插入位置private String separator; // 分割符,默认使用空格分割// 根据模板自动计算最大输入长度,超出输入无效。使用pattern时无需在xml中设置maxLength属性,若需要设置时应注意加上分隔符的数量private int maxLength;private boolean hasNoSeparator; // 设置为true时功能同EditTextprivate boolean customizeMarkerEnable; // 自定义右侧Marker点击选项使能private ShowMarkerTime mShowMarkerTime; // 自定义选项后选项显示的时间,默认输入后显示private Paint mTextPaint;private Rect mRect;private Rect mTextRect;private Bitmap mBitmap;private Paint mBitPaint;private boolean iOSStyleEnable; // 仿iOS风格,目前需要结合shape.xml的方式设置外边框private boolean iOSFrameHide;private CharSequence mHintCharSeq;public XEditText(Context context) {this(context, null);}public XEditText(Context context, AttributeSet attrs) {this(context, attrs, android.R.attr.editTextStyle); // Attention !}public XEditText(Context context, AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.XEditText, defStyleAttr, 0);separator = a.getString(R.styleable.XEditText_x_separator);if (separator == null)separator = SPACE;customizeMarkerEnable = a.getBoolean(R.styleable.XEditText_x_customizeMarkerEnable, false);int which = a.getInt(R.styleable.XEditText_x_showMarkerTime, 0);switch (which) {case 0:mShowMarkerTime = ShowMarkerTime.AFTER_INPUT;break;case 1:mShowMarkerTime = ShowMarkerTime.BEFORE_INPUT;break;case 2:mShowMarkerTime = ShowMarkerTime.ALWAYS;break;}iOSStyleEnable = a.getBoolean(R.styleable.XEditText_x_iOSStyleEnable, false);a.recycle();init();}private void init() {// 如果设置 inputType="number" 的话是没法插入空格的,所以强行转为inputType="phone"if (getInputType() == InputType.TYPE_CLASS_NUMBER)setInputType(InputType.TYPE_CLASS_PHONE);setPattern(DEFAULT_PATTERN);mTextWatcher = new MyTextWatcher();this.addTextChangedListener(mTextWatcher);mRightMarkerDrawable = getCompoundDrawables()[2];if (customizeMarkerEnable && mRightMarkerDrawable != null) { // 如果自定义Marker,暂时不显示rightDrawablesetCompoundDrawables(getCompoundDrawables()[0], getCompoundDrawables()[1], null, getCompoundDrawables()[3]);}if (mRightMarkerDrawable == null) { // 如未设置则采用默认mRightMarkerDrawable = getResources().getDrawable(R.drawable.contentseparatoredittext_clear);if (mRightMarkerDrawable != null)mRightMarkerDrawable.setBounds(0, 0, mRightMarkerDrawable.getIntrinsicWidth(),mRightMarkerDrawable.getIntrinsicHeight());}setOnFocusChangeListener(new OnFocusChangeListener() {@Overridepublic void onFocusChange(View v, boolean hasFocus) {hasFocused = hasFocus;markerFocusChangeLogic();iOSFocusChangeLogic();}});if (iOSStyleEnable)initiOSObjects();}private void initiOSObjects() {mLeftDrawable = getCompoundDrawables()[0];if (mLeftDrawable != null) {if (mBitmap == null || mBitPaint == null) {BitmapDrawable bd = (BitmapDrawable) mLeftDrawable;mBitmap = bd.getBitmap();mBitPaint = new Paint();mBitPaint.setAntiAlias(true);}setCompoundDrawables(null, getCompoundDrawables()[1], getCompoundDrawables()[2], getCompoundDrawables()[3]);}mHintCharSeq = getHint();if (mHintCharSeq != null) {setHint("");if (mRect == null || mTextRect == null || mTextPaint == null) {mRect = new Rect(getLeft(), getTop(), getWidth(), getHeight());mTextRect = new Rect();mTextPaint = new Paint();mTextPaint.setAntiAlias(true);mTextPaint.setTextSize(getTextSize());mTextPaint.setColor(getCurrentHintTextColor());mTextPaint.setTextAlign(Paint.Align.CENTER);mTextPaint.getTextBounds(mHintCharSeq.toString(), 0, mHintCharSeq.length(), mTextRect);}}iOSFrameHide = false;}@Overrideprotected void onDraw(Canvas canvas) {super.onDraw(canvas);if (iOSStyleEnable) {if (iOSFrameHide)return;if (mHintCharSeq != null) {Paint.FontMetricsInt fontMetrics = mTextPaint.getFontMetricsInt();int textCenterY = (mRect.bottom + mRect.top - fontMetrics.bottom - fontMetrics.top) / 2;canvas.drawText(mHintCharSeq.toString(), canvas.getWidth() / 2, canvas.getHeight() / 2 + textCenterY,mTextPaint);}if (mBitmap != null) {canvas.drawBitmap(mBitmap, (canvas.getWidth() - mTextRect.width()) / 2 - mBitmap.getWidth()- getCompoundDrawablePadding(), (canvas.getHeight() - mBitmap.getHeight()) / 2, mBitPaint);}}}/** * 监听右侧Marker图标点击事件 */@Overridepublic boolean onTouchEvent(MotionEvent event) {if (hasFocused && mRightMarkerDrawable != null && event.getAction() == MotionEvent.ACTION_UP) {Rect rect = mRightMarkerDrawable.getBounds();int height = rect.height();int rectTopY = (getHeight() - height) / 2;boolean isAreaX = event.getX() >= (getWidth() - getTotalPaddingRight())&& event.getX() <= (getWidth() - getPaddingRight());boolean isAreaY = event.getY() >= rectTopY && event.getY() <= (rectTopY + height);if (isAreaX && isAreaY) {if (customizeMarkerEnable) {if (mMarkerClickListener != null)mMarkerClickListener.onMarkerClick(event.getRawX(), event.getRawY());} else {setError(null);setText("");}}}return super.onTouchEvent(event);}/** * 自定义分隔符 */public void setSeparator(String separator) {if (separator == null) {throw new IllegalArgumentException("separator can't be null !");}this.separator = separator;}/** * 自定义分割模板 * @param pattern 每一段的字符个数的数组 */public void setPattern(int[] pattern) {if (pattern == null) {throw new IllegalArgumentException("pattern can't be null !");}this.pattern = pattern;intervals = new int[pattern.length];int count = 0;int sum = 0;for (int i = 0; i < pattern.length; i++) {sum += pattern[i];intervals[i] = sum + count;if (i < pattern.length - 1)count++;}maxLength = intervals[intervals.length - 1];}/** * 自定义输入框最右边Marker图标 */public void setRightMarkerDrawable(int resId) {mRightMarkerDrawable = getResources().getDrawable(resId);}/** * 输入待转换格式的字符串 */public void setTextToSeparate(CharSequence c) {if (c == null || c.length() == 0)return;setText("");for (int i = 0; i < c.length(); i++) {append(c.subSequence(i, i + 1));}}/** * 获得除去分割符的输入框内容 */public String getNonSeparatorText() {return getText().toString().replaceAll(separator, "");}/** * 是否自定义Marker */public void setCustomizeMarkerEnable(boolean customizeMarkerEnable) {this.customizeMarkerEnable = customizeMarkerEnable;if (customizeMarkerEnable && mRightMarkerDrawable != null) { // 如果自定义Marker,暂时不显示rightDrawablesetCompoundDrawables(getCompoundDrawables()[0], getCompoundDrawables()[1], null, getCompoundDrawables()[3]);}}/** * Marker在什么时间显示 * @param showMarkerTime BEFORE_INPUT:没有输入内容时显示; AFTER_INPUT:有输入内容后显示; *            ALWAYS:(获得焦点后)一直显示 */public void setShowMarkerTime(ShowMarkerTime showMarkerTime) {mShowMarkerTime = showMarkerTime;}/** * @return 是否有分割符 */public boolean hasNoSeparator() {return hasNoSeparator;}/** * @param hasNoSeparator true设置无分隔符模式,功能同EditText */public void setHasNoSeparator(boolean hasNoSeparator) {this.hasNoSeparator = hasNoSeparator;if (hasNoSeparator)separator = "";}/** * @param iOSStyleEnable true:开启仿iOS风格编辑框模式 */public void setiOSStyleEnable(boolean iOSStyleEnable) {this.iOSStyleEnable = iOSStyleEnable;initiOSObjects();invalidate();}/** * 设置OnTextChangeListener,同EditText.addOnTextChangeListener() */public void setOnTextChangeListener(OnTextChangeListener listener) {this.mTextChangeListener = listener;}/** * 设置OnMarkerClickListener,Marker被点击的监听 */public void setOnMarkerClickListener(OnMarkerClickListener markerClickListener) {mMarkerClickListener = markerClickListener;}// =========================== MyTextWatcher// ================================private class MyTextWatcher implements TextWatcher {@Overridepublic void beforeTextChanged(CharSequence s, int start, int count, int after) {preLength = s.length();if (mTextChangeListener != null)mTextChangeListener.beforeTextChanged(s, start, count, after);}@Overridepublic void onTextChanged(CharSequence s, int start, int before, int count) {currLength = s.length();if (hasNoSeparator)maxLength = currLength;markerFocusChangeLogic();if (currLength > maxLength) {getText().delete(currLength - 1, currLength);return;}for (int i = 0; i < pattern.length; i++) {if (currLength == intervals[i]) {if (currLength > preLength) { // 正在输入if (currLength < maxLength) {removeTextChangedListener(mTextWatcher);mTextWatcher = null;getText().insert(currLength, separator);}} else if (preLength <= maxLength) { // 正在删除removeTextChangedListener(mTextWatcher);mTextWatcher = null;getText().delete(currLength - 1, currLength);}if (mTextWatcher == null) {mTextWatcher = new MyTextWatcher();addTextChangedListener(mTextWatcher);}break;}}if (mTextChangeListener != null)mTextChangeListener.onTextChanged(s, start, before, count);}@Overridepublic void afterTextChanged(Editable s) {if (mTextChangeListener != null)mTextChangeListener.afterTextChanged(s);}}private void markerFocusChangeLogic() {if (!hasFocused) {setCompoundDrawables(getCompoundDrawables()[0], getCompoundDrawables()[1], null, getCompoundDrawables()[3]);return;}Drawable drawable = null;switch (mShowMarkerTime) {case ALWAYS:drawable = mRightMarkerDrawable;break;case BEFORE_INPUT:if (currLength == 0)drawable = mRightMarkerDrawable;break;case AFTER_INPUT:if (currLength > 0)drawable = mRightMarkerDrawable;break;}setCompoundDrawables(getCompoundDrawables()[0], getCompoundDrawables()[1], drawable, getCompoundDrawables()[3]);}private void iOSFocusChangeLogic() {if (!iOSStyleEnable)return;if (hasFocused) {if (mLeftDrawable != null)setCompoundDrawables(mLeftDrawable, getCompoundDrawables()[1], getCompoundDrawables()[2],getCompoundDrawables()[3]);if (mHintCharSeq != null)setHint(mHintCharSeq);iOSFrameHide = true;invalidate();} else {if (currLength == 0) { // 编辑框无内容恢复居中状态initiOSObjects();invalidate();}}}public interface OnTextChangeListener {void beforeTextChanged(CharSequence s, int start, int count, int after);void onTextChanged(CharSequence s, int start, int before, int count);void afterTextChanged(Editable s);}public interface OnMarkerClickListener {/** * @param x 被点击点相对于屏幕的x坐标 * @param y 被点击点相对于屏幕的y坐标 */void onMarkerClick(float x, float y);}public enum ShowMarkerTime {BEFORE_INPUT, AFTER_INPUT, ALWAYS}}

package com.z.customedittext;import android.content.Context;import android.graphics.drawable.ColorDrawable;import android.view.Gravity;import android.view.View;import android.view.ViewGroup;import android.view.WindowManager;import android.widget.PopupWindow;public class MarkerPopWindow extends PopupWindow {    public MarkerPopWindow(Context context, View rootLayout, int x, int y) {        super(context);        View view = View.inflate(context, R.layout.layout_pop_up, null);        this.setContentView(view);        this.setBackgroundDrawable(new ColorDrawable(0x00000000));        this.setFocusable(true);        this.setSoftInputMode(PopupWindow.INPUT_METHOD_NEEDED);        this.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE);        this.setOutsideTouchable(true);        this.setWidth(ViewGroup.LayoutParams.WRAP_CONTENT);        this.setHeight(ViewGroup.LayoutParams.WRAP_CONTENT);        this.setAnimationStyle(R.style.Anim);        this.showAtLocation(rootLayout, Gravity.BOTTOM, x, y);    }}
重要代码都在上面了。。。。

源码下载:点击打开链接

1 0
原创粉丝点击