All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.WazaBe.HoloEverywhere.widget.MultiAutoCompleteTextView Maven / Gradle / Ivy

The newest version!
package com.WazaBe.HoloEverywhere.widget;

import android.annotation.SuppressLint;
import android.content.Context;
import android.text.Editable;
import android.text.SpannableString;
import android.text.Spanned;
import android.text.TextUtils;
import android.text.method.QwertyKeyListener;
import android.util.AttributeSet;
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityNodeInfo;
import android.widget.Filter;

public class MultiAutoCompleteTextView extends AutoCompleteTextView {
	public static class CommaTokenizer implements Tokenizer {
		@Override
		public int findTokenEnd(CharSequence text, int cursor) {
			int i = cursor;
			int len = text.length();
			while (i < len) {
				if (text.charAt(i) == ',') {
					return i;
				} else {
					i++;
				}
			}
			return len;
		}

		@Override
		public int findTokenStart(CharSequence text, int cursor) {
			int i = cursor;
			while (i > 0 && text.charAt(i - 1) != ',') {
				i--;
			}
			while (i < cursor && text.charAt(i) == ' ') {
				i++;
			}
			return i;
		}

		@Override
		public CharSequence terminateToken(CharSequence text) {
			int i = text.length();
			while (i > 0 && text.charAt(i - 1) == ' ') {
				i--;
			}
			if (i > 0 && text.charAt(i - 1) == ',') {
				return text;
			} else {
				if (text instanceof Spanned) {
					SpannableString sp = new SpannableString(text + ", ");
					TextUtils.copySpansFrom((Spanned) text, 0, text.length(),
							Object.class, sp, 0);
					return sp;
				} else {
					return text + ", ";
				}
			}
		}
	}

	public static interface Tokenizer {
		public int findTokenEnd(CharSequence text, int cursor);

		public int findTokenStart(CharSequence text, int cursor);

		public CharSequence terminateToken(CharSequence text);
	}

	private Tokenizer mTokenizer;

	public MultiAutoCompleteTextView(Context context) {
		super(context);
	}

	public MultiAutoCompleteTextView(Context context, AttributeSet attrs) {
		super(context, attrs);
	}

	public MultiAutoCompleteTextView(Context context, AttributeSet attrs,
			int defStyle) {
		super(context, attrs, defStyle);
	}

	@Override
	public boolean enoughToFilter() {
		Editable text = getText();
		int end = getSelectionEnd();
		if (end < 0 || mTokenizer == null) {
			return false;
		}
		int start = mTokenizer.findTokenStart(text, end);
		if (end - start >= getThreshold()) {
			return true;
		} else {
			return false;
		}
	}

	@Override
	public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
		super.onInitializeAccessibilityEvent(event);
		event.setClassName(MultiAutoCompleteTextView.class.getName());
	}

	@Override
	@SuppressLint("NewApi")
	public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
		super.onInitializeAccessibilityNodeInfo(info);
		info.setClassName(MultiAutoCompleteTextView.class.getName());
	}

	@Override
	protected void onLoadEntries(CharSequence[] entries) {
		super.onLoadEntries(entries);
		if (mTokenizer == null) {
			setTokenizer(new CommaTokenizer());
		}
	}

	@Override
	protected void performFiltering(CharSequence text, int keyCode) {
		if (enoughToFilter()) {
			int end = getSelectionEnd();
			int start = mTokenizer.findTokenStart(text, end);
			performFiltering(text, start, end, keyCode);
		} else {
			dismissDropDown();
			Filter f = getFilter();
			if (f != null) {
				f.filter(null);
			}
		}
	}

	protected void performFiltering(CharSequence text, int start, int end,
			int keyCode) {
		getFilter().filter(text.subSequence(start, end), this);
	}

	@Override
	public void performValidation() {
		Validator v = getValidator();
		if (v == null || mTokenizer == null) {
			return;
		}
		Editable e = getText();
		int i = getText().length();
		while (i > 0) {
			int start = mTokenizer.findTokenStart(e, i);
			int end = mTokenizer.findTokenEnd(e, start);
			CharSequence sub = e.subSequence(start, end);
			if (TextUtils.isEmpty(sub)) {
				e.replace(start, i, "");
			} else if (!v.isValid(sub)) {
				e.replace(start, i, mTokenizer.terminateToken(v.fixText(sub)));
			}
			i = start;
		}
	}

	@Override
	protected void replaceText(CharSequence text) {
		clearComposingText();
		int end = getSelectionEnd();
		int start = mTokenizer.findTokenStart(getText(), end);
		Editable editable = getText();
		String original = TextUtils.substring(editable, start, end);
		QwertyKeyListener.markAsReplaced(editable, start, end, original);
		editable.replace(start, end, mTokenizer.terminateToken(text));
	}

	public void setTokenizer(Tokenizer t) {
		mTokenizer = t;
	}
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy