Android 邮箱自动补全-MultiAutoCompleteTextView实现

因为项目需要,要写一个邮箱自动补全的EditText,刚开始考虑使用AutoCompleteTextView来实现,但是满足不到需求官方组件太low了。。。

先来介绍下AutoCompleteTextView 的使用:
Activity

import android.os.Bundle; import android.support.v7.app.AppCompatActivity; import android.widget.ArrayAdapter; import android.widget.AutoCompleteTextView; public class MainActivity extends AppCompatActivity { private static final String[] COUNTRIES = new String[]{ "Belgium", "France", "Italy", "Germany", "Spain" }; private AutoCompleteTextView mAutoCompleteTextView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mAutoCompleteTextView = (AutoCompleteTextView) findViewById(R.id.autoCompleteTextView); ArrayAdapter<String> adapter = new ArrayAdapter(this, android.R.layout.simple_dropdown_item_1line, COUNTRIES); mAutoCompleteTextView.setAdapter(adapter); } }

XML

<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="20dp" android:text="AutoCompleteTextView实现" android:textColor="@android:color/black" /> <AutoCompleteTextView android:id="@ id/autoCompleteTextView" android:layout_width="match_parent" android:layout_height="wrap_content" android:completionThreshold="1"/> </LinearLayout>

使用方法很简单,获取到组件然后设置一个弹出的Adapter就能完成一个自动提示。

但是这个组件有几个特性不是很满足我们的需求。
1.默认是第二个字母开始匹配
2.整体内容匹配模式 Belgium 我们只能输入B ,Be,Bel等才会匹配
注:邮箱格式为123456@XX.com,整体内容肯定不行。

下面我们又看到一个MultiAutoCompleteTextView组件,来看下MultiAutoCompleteTextView能否满足我们的需求

import android.os.Bundle; import android.support.v7.app.AppCompatActivity; import android.widget.ArrayAdapter; import android.widget.AutoCompleteTextView; import android.widget.MultiAutoCompleteTextView; public class MainActivity extends AppCompatActivity { private static final String[] COUNTRIES = new String[]{ "Belgium", "France", "Italy", "Germany", "Spain" }; private AutoCompleteTextView mAutoCompleteTextView; private MultiAutoCompleteTextView mMultiAutoCompleteTextView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mAutoCompleteTextView = (AutoCompleteTextView) findViewById(R.id.autoCompleteTextView); mMultiAutoCompleteTextView = (MultiAutoCompleteTextView) findViewById(R.id.multiAutoCompleteTextView); ArrayAdapter<String> adapter = new ArrayAdapter(this, android.R.layout.simple_dropdown_item_1line, COUNTRIES); mAutoCompleteTextView.setAdapter(adapter); mMultiAutoCompleteTextView.setAdapter(adapter); mMultiAutoCompleteTextView.setTokenizer(new MultiAutoCompleteTextView.CommaTokenizer()); } }

XML

<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="20dp" android:text="AutoCompleteTextView实现" android:textColor="@android:color/black" /> <AutoCompleteTextView android:id="@ id/autoCompleteTextView" android:layout_width="match_parent" android:layout_height="wrap_content" android:completionThreshold="1" /> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="20dp" android:text="MultiAutoCompleteTextView实现" android:textColor="@android:color/black" /> <MultiAutoCompleteTextView android:id="@ id/multiAutoCompleteTextView" android:layout_width="match_parent" android:layout_height="wrap_content" android:completionThreshold="1" /> </LinearLayout>

Activity
经过查询API 我们知道 MultiAutoCompleteTextView 继承于 AutoCompleteTextView 继承于EditText

API中在MultiAutoCompleteTextView 提供了一个接口MultiAutoCompleteTextView.Tokenizer 可以用来匹配提示的子字符串。好吧,勉强能实现需求。
首先看MultiAutoCompleteTextView源码中有一个对Tokenizer接口的实现!然后换成我们的。

/** * This simple Tokenizer can be used for lists where the items are * separated by a comma and one or more spaces. */ public static class CommaTokenizer implements Tokenizer { 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; } 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; } 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 ", "; } } } }

根据MultiAutoCompleteTextView源码中的实现,我们知道Tokenizer的实现方式。

import android.text.SpannableString; import android.text.Spanned; import android.text.TextUtils; import android.widget.MultiAutoCompleteTextView; public class EmailAutoTokenizer implements MultiAutoCompleteTextView.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 index = text.toString().indexOf("@"); if (index < 0) { index = text.length(); } if (index >= findTokenEnd(text, cursor)) { index = 0; } return index; } @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; } } } }

在Activity中把Tokenizer换成我们自己的看下效果 mMultiAutoCompleteTextView.setTokenizer(new EmailAutoTokenizer());

import android.os.Bundle; import android.support.v7.app.AppCompatActivity; import android.widget.ArrayAdapter; import android.widget.AutoCompleteTextView; import android.widget.MultiAutoCompleteTextView; public class MainActivity extends AppCompatActivity { private String[] email_sufixs = new String[]{"@qq.com", "@163.com", "@126.com", "@gmail.com", "@sina.com", "@hotmail.com", "@yahoo.cn", "@sohu.com", "@foxmail.com", "@139.com", "@yeah.net", "@vip.qq.com", "@vip.sina.com"}; private AutoCompleteTextView mAutoCompleteTextView; private MultiAutoCompleteTextView mMultiAutoCompleteTextView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mAutoCompleteTextView = (AutoCompleteTextView) findViewById(R.id.autoCompleteTextView); mMultiAutoCompleteTextView = (MultiAutoCompleteTextView) findViewById(R.id.multiAutoCompleteTextView); ArrayAdapter<String> adapter = new ArrayAdapter(this, android.R.layout.simple_dropdown_item_1line, email_sufixs); mAutoCompleteTextView.setAdapter(adapter); mMultiAutoCompleteTextView.setAdapter(adapter); mMultiAutoCompleteTextView.setTokenizer(new EmailAutoTokenizer()); } }

看下最后的效果图,当然我们还需要对弹出框进行调整下,自己去查询API吧!提供有方法。

正当我高兴的时候,万恶的产品Dog给我加一个右边删除效果,丢一个验证规则过来!

在@之后输入字母,从输入的字母开始suggest邮箱
点击suggest的邮箱,邮箱被输入到邮箱输入栏里,光标移动到下一text box
例:
1. 输入:monoqn → 不suggest
1. 输入:monoqn@ → 不suggest
1. 输入:monoqn@i → monoqn@i.softbank.jp/monoqn@icloud.com
1. 输入:monoqn@ic → monoqn@icloud.com

下面先验证规则:
1.在@之后输入字母,从输入的字母开始suggest邮箱。
很简单android:completionThreshold=”2” 设置输入几个字符之后显示下拉菜单,默认为2个。不用管就行
2.点击suggest的邮箱,邮箱被输入到邮箱输入栏里,光标移动到下一text box
也简单MultiAutoCompleteTextView中有OnItemClickListener事件,

email.setOnItemClickListener((parent, view1, position, id) -> password.requestFocus());

3.显示规则
看下了满足需求,666666!

最后一个右边加入删除按钮!本宝宝自定义一个就OK。

import android.content.Context; import android.graphics.drawable.Drawable; import android.text.Editable; import android.text.TextUtils; import android.text.TextWatcher; import android.util.AttributeSet; import android.view.MotionEvent; import android.view.View; import android.widget.MultiAutoCompleteTextView; public class CleanableMultiAutoCompleteTextView extends MultiAutoCompleteTextView { private Drawable mRightDrawable; public CleanableMultiAutoCompleteTextView(Context context) { super(context); init(); } public CleanableMultiAutoCompleteTextView(Context context, AttributeSet attrs) { super(context, attrs); init(); } public CleanableMultiAutoCompleteTextView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); init(); } private void init() { // getCompoundDrawables: // Returns drawables for the left, top, right, and bottom borders. Drawable[] drawables = this.getCompoundDrawables(); // get right drawable in layout.xml that is android:drawableRight mRightDrawable = drawables[2]; setOnFocusChangeListener(new FocusChangeListenerImpl()); addTextChangedListener(new TextWatcherImpl()); setClearDrawableVisible(false); } @Override public boolean onTouchEvent(MotionEvent event) { switch (event.getAction()) { case MotionEvent.ACTION_UP: boolean isClean = (event.getX() > (getWidth() – getTotalPaddingRight())) && (event.getX() < (getWidth() – getPaddingRight())); if (isClean) { setText(""); } break; } return super.onTouchEvent(event); } private class FocusChangeListenerImpl implements OnFocusChangeListener { @Override public void onFocusChange(View v, boolean hasFocus) { if (hasFocus) { boolean isVisible = !TextUtils.isEmpty(getText()); setClearDrawableVisible(isVisible); } else { setClearDrawableVisible(false); } } } private class TextWatcherImpl implements TextWatcher { @Override public void afterTextChanged(Editable s) { boolean isVisible = !TextUtils.isEmpty(getText()); setClearDrawableVisible(isVisible); } @Override public void beforeTextChanged(CharSequence s, int start, int count, int after) { // no-op } @Override public void onTextChanged(CharSequence s, int start, int before, int count) { // no-op } } public void setClearDrawableVisible(boolean isVisible) { Drawable rightDrawable = isVisible ? mRightDrawable : null; setCompoundDrawables(getCompoundDrawables()[0], getCompoundDrawables()[1], rightDrawable, getCompoundDrawables()[3]); } }

 

更多关于云服务器域名注册虚拟主机的问题,请访问西部数码官网:www.west.cn

赞(2)
声明:本网站发布的内容(图片、视频和文字)以原创、转载和分享网络内容为主,如果涉及侵权请尽快告知,我们将会在第一时间删除。文章观点不代表本网站立场,如需处理请联系客服。电话:028-62778877-8306;邮箱:fanjiao@west.cn。本站原创内容未经允许不得转载,或转载时需注明出处:西部数码知识库 » Android 邮箱自动补全-MultiAutoCompleteTextView实现

登录

找回密码

注册