使用AutoCompleteTextView實現郵箱地址補全

最近學習android時,用到AutoCompleteTextView,感受挺有意思,因而模仿着網易郵箱地址補全的效果也實現了一個。 java

AutoCompleteTextView是一個具備自動補全功能的EditView,當用戶輸入數據後,AutoCompleteTextView就會將用戶輸入的數據與他本身的adapter中的數據對比,若是用戶數據與adapter中的某條數據的開始部分徹底匹配,那麼adapter中的這條數據就會出如今下拉提示框中。 android

例如:adapter中有3條數據「abc」,「hjk」,「abd」,而用戶輸入「ab」,那麼下拉提示框中將會出現「abc」和「abd」。(AutoCompleteTextView默認在用戶輸入兩個字符以後才提示,能夠經過setThreshold(1)來將它設置爲用戶輸入1個字符後就開始提示) ide

AutoCompleteTextView在匹配用戶輸入數據時,會調用performFiltering方法,將用戶數據傳入,並調用adapter的filter來處理。 學習

由於當用戶選中下拉列表中的某一項時,AutoCompleteTextView會使用該項對應的adapter中的數據來填充文本域,這與咱們這邊的需求不太相同,由於咱們的adapter中只有相似於「@163.com」的email地址後綴,下拉框中的數據是咱們將用戶輸入和adapter中的數據拼接而成的。所以咱們須要重寫replaceText方法,以使AutoCompleteTextView來在用戶選中某一項時,用咱們指定的文原本填充文本域。 測試

而後咱們須要爲AutoCompleteTextView設置OnFocusChangeListener來在用戶移開焦點後,進行email地址格式檢查,而且在再次得到焦點後重啓提示功能。 this

代碼以下:(EmailAutoCompleteTextView.java spa

public class EmailAutoCompleteTextView extends AutoCompleteTextView {
	private static final String TAG = "EmailAutoCompleteTextView";

	private String[] emailSufixs = new String[] { "@163.com",
		"@gmail.com", "@hotmail.com" };

	public EmailAutoCompleteTextView(Context context) {
		super(context);
		init(context);
	}

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

	public EmailAutoCompleteTextView(Context context, AttributeSet attrs,
			int defStyle) {
		super(context, attrs, defStyle);
		init(context);
	}
	
	public void setAdapterString(String[] es) {
		if(es != null && es.length > 0)
			this.emailSufixs = es;
	}
	
	private void init(final Context context) {
		//adapter中使用默認的emailSufixs中的數據,能夠經過setAdapterString來更改
		this.setAdapter(new EmailAutoCompleteAdapter(context, R.layout.auto_complete_item, emailSufixs));
		
		//使得在輸入1個字符以後便開啓自動完成
		this.setThreshold(1);

		this.setOnFocusChangeListener(new OnFocusChangeListener() {
			
			@Override
			public void onFocusChange(View v, boolean hasFocus) {
				if(hasFocus) {
					String text = EmailAutoCompleteTextView.this.getText().toString();
					//當該文本域從新得到焦點後,重啓自動完成
					if(!"".equals(text))
						performFiltering(text, 0);
				} else {
					//當文本域丟失焦點後,檢查輸入email地址的格式
					EmailAutoCompleteTextView ev = (EmailAutoCompleteTextView) v;
					String text = ev.getText().toString();
					//這裏正則寫的有點粗暴:)
					if(text != null && text.matches("^[a-zA-Z0-9_]+@[a-zA-Z0-9]+\\.[a-zA-Z0-9]+$")) {
						Toast to = new Toast(context);
						ImageView i = new ImageView(context);
						i.setBackgroundResource(R.drawable.img_success);
						to.setView(i);
						to.show();
					} else {
						Toast toast = Toast.makeText(context, "郵件地址格式不正確", Toast.LENGTH_SHORT);
						toast.setGravity(Gravity.TOP, 0, 50);
						toast.show();
					}
				}
			}
		});
	}
	
	

	@Override
	protected void replaceText(CharSequence text) {
		//當咱們在下拉框中選擇一項時,android會默認使用AutoCompleteTextView中Adapter裏的文原本填充文本域
		//由於這裏Adapter中只是存了經常使用email的後綴
		//所以要從新replace邏輯,將用戶輸入的部分與後綴合併
		Log.i(TAG + " replaceText", text.toString());
		String t = this.getText().toString();
		int index = t.indexOf("@");
		if(index != -1)
			t = t.substring(0, index);
		super.replaceText(t + text);
	}

	@Override
	protected void performFiltering(CharSequence text, int keyCode) {
		//該方法會在用戶輸入文本以後調用,將已輸入的文本與adapter中的數據對比,若它匹配
		//adapter中數據的前半部分,那麼adapter中的這條數據將會在下拉框中出現
		Log.i(TAG + " performFiltering", text.toString() + "   " + keyCode);
		String t = text.toString();
		
		//由於用戶輸入郵箱時,都是以字母,數字開始,而咱們的adapter中只會提供以相似於"@163.com"
		//的郵箱後綴,所以在調用super.performFiltering時,傳入的必定是以"@"開頭的字符串
		int index = t.indexOf("@");
		if(index == -1) {
			if(t.matches("^[a-zA-Z0-9_]+$")) {
				super.performFiltering("@", keyCode);
			}
			else
				this.dismissDropDown();//當用戶中途輸入非法字符時,關閉下拉提示框
		} else {
			super.performFiltering(t.substring(index), keyCode);
		}
	}

	
	private class EmailAutoCompleteAdapter extends ArrayAdapter<String> {

		public EmailAutoCompleteAdapter(Context context, int textViewResourceId, String[] email_s) {
			super(context, textViewResourceId, email_s);
		}

		@Override
		public View getView(int position, View convertView, ViewGroup parent) {
			Log.i(TAG, "in GetView");
			View v = convertView;
			if (v == null)
				v = LayoutInflater.from(getContext()).inflate(
						R.layout.auto_complete_item, null);
			TextView tv = (TextView) v.findViewById(R.id.tv);
			
			String t = EmailAutoCompleteTextView.this.getText().toString();
			int index = t.indexOf("@");
			if(index != -1)
				t = t.substring(0, index);
			//將用戶輸入的文本與adapter中的email後綴拼接後,在下拉框中顯示
			tv.setText(t + getItem(position));
			Log.i(TAG, tv.getText().toString());
			return v;
		}
	}
}
activity的xml文件以下:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >

    <com.example.testautocompletetextview.EmailAutoCompleteTextView
        android:id="@+id/act"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="Email Address"
        android:textColor="@color/black" />

    <!-- 用於測試移開焦點 -->
    <EditText
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="20dp"
        android:drawableLeft="@drawable/amount_selected" />

</LinearLayout>
下拉提示框中每一項(TextView)的xml:

<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/tv"
    android:padding="8dp"
    android:layout_width="match_parent"
    android:layout_height="wrap_content" />

提示截圖: code





相關文章
相關標籤/搜索