Android 带分隔符的EditText

先看效果图,这个也是从网上来的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;

	@Override
	protected 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() {
			@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) {
				textView1.setText(defaultSeparatorEdit.getNonSeparatorText());
			}
		});
		customSeparatorEdit.setOnTextChangeListener(new XEditText.OnTextChangeListener() {
			@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) {
				textView2.setText(customSeparatorEdit.getNonSeparatorText());
			}
		});
		button.setOnClickListener(new View.OnClickListener() {
			@Override
			public void onClick(View v) {
				showSeparatorEdit.setTextToSeparate("13800000000");
			}
		});

		customMarkerEdit1.setCustomizeMarkerEnable(true);
		customMarkerEdit1.setOnMarkerClickListener(new XEditText.OnMarkerClickListener() {
			@Override
			public 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时功能同EditText
	private 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,暂时不显示rightDrawable
			setCompoundDrawables(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() {
			@Override
			public 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;
	}

	@Override
	protected 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图标点击事件
	 */
	@Override
	public 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,暂时不显示rightDrawable
			setCompoundDrawables(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 {
		@Override
		public void beforeTextChanged(CharSequence s, int start, int count, int after) {
			preLength = s.length();
			if (mTextChangeListener != null)
				mTextChangeListener.beforeTextChanged(s, start, count, after);
		}

		@Override
		public 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);
		}

		@Override
		public 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
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值