Android SDK 提供了MultiAutoCompleteTextView 控件,可以支持从指定字符开始联想。MultiAutoCompleteTextView 通过分词器 Tokenizer,可以支持连续提示
下面是运行效果图:
只要输入“@”符号就会自动联想邮箱。
下面是自定义的 MailBoxAssociateView 类继承于
AppCompatMultiAutoCompleteTextView 控件,来实现联想邮箱组件。
/** * @desciption: 邮箱联想控件,输入 @ 符后开始联想 */public class MailBoxAssociateView extends AppCompatMultiAutoCompleteTextView { public MailBoxAssociateView(Context context) { super(context); } public MailBoxAssociateView(Context context, AttributeSet attrs) { super(context, attrs); } public MailBoxAssociateView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); } /** * 当输入@符号时,就会去调用Tokenizer.findTokenStart()方法一次 * 当点击下拉提示框中的某个信息时,会再次调用Tokenizer.findTokenStart()方法一次,然后再调用terminateToken()方法一次 */ @Override public boolean enoughToFilter() { // 若用户输入的文本字符串中包含'@'字符且不在第一位,则满足条件返回true,否则返回false return getText().toString().contains("@") && getText().toString().indexOf("@") > 0; }}
如果需要输入的第一个字符是“@”就联想邮箱只需要改为以下代码即可。
@Override public boolean enoughToFilter() { return getText().toString().contains("@") ; }
自定义分词器 MailBoxAssociateTokenizer 类,指定从哪个地方开始联想字符。
/** * @desciption: 指定从哪个地方开始联想字符 */public class MailBoxAssociateTokenizer implements MultiAutoCompleteTextView.Tokenizer { /** * 用于查找当前光标位置之前的分隔符的位置并返回 * * @param text 用户已经输入的文本内容 * @param cursor 当前光标的位置,在文本内容后面 * @return */ @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; } /** * 用于查找当前光标位置之后的分隔符的位置并返回,向后查询 * * @param text 用户已经输入的文本内容 * @param cursor 当前光标的位置,在文本内容之间 * @return */ @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; } /** * 用于返回提示信息加上分隔符后的文本内容 * * @param text * @return */ @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 { // CharSequence类型的数据有可能是富文本SpannableString类型 // 故需要进行判断 if (text instanceof Spanned) { SpannableString sp = new SpannableString(text); // 故需要借助TextUtils.copySpansFrom从text中复制原来的样式到新的sp中, // 以保持原先样式不变情况下添加一个逗号和空格 TextUtils.copySpansFrom((Spanned) text, 0, text.length(), Object.class, sp, 0); return sp; } else { return text; } } }}
布局文件 :
android:id="@+id/associate_email_input" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="57dp" android:hint="@string/account" android:paddingLeft="5dp" android:paddingBottom="12dp" android:popupBackground="@drawable/bg_recommend_mail_list" android:singleLine="true" android:textColor="@color/color_333333" android:textColorHint="@color/color_bfbfbf" android:textSize="16sp"/>
使用方式
在 values 中创建 arrays.xml 文件
<string-array name="recommend_mail_box"> <item>\@gmail.comitem> <item>\@hotmail.comitem> <item>\@yahoo.comitem> <item>\@outlook.comitem> <item>\@aol.comitem> <item>\@hotmail.co.ukitem> <item>\@yahoo.co.ukitem> <item>\@mail.ruitem> <item>\@rediffmail.comitem> <item>\@live.comitem> <item>\@msn.comitem> string-array>
在 Activity中使用
mUserNameAssociateView = findViewById(R.id.associate_email_input); String[] recommendMailBox = getResources().getStringArray(R.array.recommend_mail_box); ArrayAdapter<String> adapter = new ArrayAdapter<>(this, R.layout.item_associate_mail_list, R.id.tv_recommend_mail, recommendMailBox); mUserNameAssociateView.setAdapter(adapter); mUserNameAssociateView.setTokenizer(new MailBoxAssociateTokenizer());
到这里就结束啦.