一步一步学android控件(之六) —— MultiAutoCompleteTextView

2024-02-23 10:32

本文主要是介绍一步一步学android控件(之六) —— MultiAutoCompleteTextView,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

今天学习的控件是MultiAutoCompleteTextView 。 提到MultiAutoCompleteTextView 我们就自然而然地想到AutoCompleteTextView ,就想知道他们之间到底有什么区别。在讲他们区别之前呢先来看看下面两张图片:

                                          

    (图1)AutoCompleteTextView                           (图2)MultiAutoCompleteTextView

这两张图片中使用的都是同样的Adapter , 然而在图1中输入图2中的内容时却得不到任何内容,为什么?

先从他们的关系上说说, MultiAutoCompleteTextView 继承自AutoCompleteTextView(废话 ... 囧) , 在使用上多了一个Tokenizer —— 在图2中,这个Tokenizer就是符号 ‘ , ’ ,当遇到这个符号时会根据光标的位置计算当前关注的信息。如:如果光标在  d  的位置,则 ‘ , ’之前的字串有效;如果光标在 g 位置,则 ‘ , ’ 后面的字串有效;另外如果光标前后都有符号‘ , ’ , 则在两个 ‘ , ’ 中的内容有效。对于这段解释,下面的代码获取更具说服力:

public static class SelfDedineTokenizer implements Tokenizer {private char mTokenizer = ',';public SelfDedineTokenizer() {}public SelfDedineTokenizer(char token) {mTokenizer = token;}public int findTokenEnd(CharSequence text, int cursor) {int i = cursor;int len = text.length();while (i < len) {if (text.charAt(i) == mTokenizer) {return i;} else {i++;}}return len;}public int findTokenStart(CharSequence text, int cursor) {int i = cursor;while (i > 0 && text.charAt(i - 1) != mTokenizer) {i--;}while (i < cursor && text.charAt(i) == ' ') {i++;}return i;}public CharSequence terminateToken(CharSequence text) {int i = text.length();while (i > 0 && text.charAt(i - 1) == ' ') {i--;}if (i > 0 && text.charAt(i - 1) == mTokenizer) {return text;} else {if (text instanceof Spanned) {SpannableString sp = new SpannableString(text+ String.valueOf(mTokenizer));TextUtils.copySpansFrom((Spanned) text, 0, text.length(),Object.class, sp, 0);return sp;} else {return text + String.valueOf(mTokenizer);}}}public void setToken(char token) {mTokenizer = token;}public char getToken() {return mTokenizer;}}
这段代码是自定义的Tokenizer , 默认使用 ‘ , ’ 作为分隔符, 若想用其他的符号替换 ‘ , ’ 使用setToken方法即可。


废话也说了那么多了,现在说说今天要做的事情

1、使用异步调用方法(Executors)加载MultiAutoCompleteTextView 中 Adapter 需要的数据(数据跟AutoCompleteTextView一样,有疑问的可参见 点击一步一步学android控件(之五) —— AutoCompleteTextView)

2、在MultiAutoCompleteTextView中使用自定义的Tokenizer而不是默认的Tokenizer。


下面就来实现这些功能,老规矩先准备资源文件

1、 创建布局文件 multi_auto_complete_textview.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" ><MultiAutoCompleteTextViewandroid:id="@+id/show_multi_complete"android:layout_width="match_parent"android:layout_height="wrap_content"android:padding="10dp"android:layout_marginTop="20dp" /></LinearLayout>
2、创建activity ——WidgetMultiAutoCompleteActivity.java
package com.xy.zt.selfdefinewieget;import java.io.File;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;import android.annotation.SuppressLint;
import android.app.Activity;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.os.Message;
import android.text.SpannableString;
import android.text.Spanned;
import android.text.TextUtils;
import android.widget.ArrayAdapter;
import android.widget.MultiAutoCompleteTextView;
import android.widget.MultiAutoCompleteTextView.Tokenizer;public class WidgetMultiAutoCompleteActivity extends Activity {public static final String[] DEFAULT_DATAS = new String[] { "China","chengdu", "xueyu", "ting", "baba", "mama", "meimei" };public static final int MSG_RECEIVE_TASK_DATA = 1024;private ExecutorService mExecutor;private ArrayAdapter<String> mMultiAdapter;private MultiAutoCompleteTextView mShowMulti;// private CommaTokenizer mComma = new CommaTokenizer();private Future<List<String>> mListFileTask;private static final Callable<List<String>> LIST_FILES = new Callable<List<String>>() {public List<String> call() throws Exception {File rootDir = Environment.getRootDirectory();LinkedList<File> queue = new LinkedList<File>();ArrayList<String> result = new ArrayList<String>(100);queue.offer(rootDir);File tmpFile, tmpDirAllFile[];while ((tmpFile = queue.poll()) != null) {if (tmpFile.isDirectory()) {tmpDirAllFile = tmpFile.listFiles();if (tmpDirAllFile != null) {for (File f : tmpDirAllFile) {queue.offer(f);}}} else {result.add(tmpFile.getName());}}return result;}};Handler mHandler = new Handler() {@SuppressWarnings("unchecked")@Overridepublic void handleMessage(Message msg) {switch (msg.what) {case MSG_RECEIVE_TASK_DATA:List<String> datas;try {datas = (List<String>) msg.obj;} catch (ClassCastException e) {datas = useDefaultData();}mShowMulti.setEnabled(true);mMultiAdapter = new ArrayAdapter<String>(WidgetMultiAutoCompleteActivity.this,R.layout.auto_complete_item, R.id.auto_item_file_name,datas);mShowMulti.setAdapter(mMultiAdapter);break;};}};@Overridepublic void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.multi_auto_complete_textview);init();mExecutor = Executors.newCachedThreadPool();mListFileTask = mExecutor.submit(LIST_FILES);mExecutor.submit(new Runnable() {@SuppressLint("HandlerLeak")public void run() {List<String> datas;try {datas = mListFileTask.get();} catch (InterruptedException e) {datas = useDefaultData();} catch (ExecutionException e) {datas = useDefaultData();}Message msg = mHandler.obtainMessage(MSG_RECEIVE_TASK_DATA);msg.obj = datas;mHandler.sendMessage(msg);}});}void init() {mShowMulti = (MultiAutoCompleteTextView) findViewById(R.id.show_multi_complete);mShowMulti.setEnabled(false);mShowMulti.setTokenizer(mCustomerToken);mShowMulti.setThreshold(1);}private List<String> useDefaultData() {List<String> datas = new ArrayList<String>();for (String s : DEFAULT_DATAS) {datas.add(s);}return datas;}@Overrideprotected void onDestroy() {super.onDestroy();mExecutor.shutdown();}SelfDedineTokenizer mCustomerToken = new SelfDedineTokenizer(';');public static class SelfDedineTokenizer implements Tokenizer {private char mTokenizer = ',';public SelfDedineTokenizer() {}public SelfDedineTokenizer(char token) {mTokenizer = token;}public int findTokenEnd(CharSequence text, int cursor) {int i = cursor;int len = text.length();while (i < len) {if (text.charAt(i) == mTokenizer) {return i;} else {i++;}}return len;}public int findTokenStart(CharSequence text, int cursor) {int i = cursor;while (i > 0 && text.charAt(i - 1) != mTokenizer) {i--;}while (i < cursor && text.charAt(i) == ' ') {i++;}return i;}public CharSequence terminateToken(CharSequence text) {int i = text.length();while (i > 0 && text.charAt(i - 1) == ' ') {i--;}if (i > 0 && text.charAt(i - 1) == mTokenizer) {return text;} else {if (text instanceof Spanned) {SpannableString sp = new SpannableString(text+ String.valueOf(mTokenizer));TextUtils.copySpansFrom((Spanned) text, 0, text.length(),Object.class, sp, 0);return sp;} else {return text + String.valueOf(mTokenizer);}}}public void setToken(char token) {mTokenizer = token;}public char getToken() {return mTokenizer;}}
}
今天主要的内容就在这个文件中,先来看看

 private static final Callable<List<String>> LIST_FILES = new Callable<List<String>>()
Callable接口类似于Runnable,只是他是有返回结果的Runnable , 在他的call方法中做搜索系统文件的工作。  在onCreat函数中有下面代码:

mExecutor = Executors.newCachedThreadPool();mListFileTask = mExecutor.submit(LIST_FILES);
这段代码第一句创建了一个线程池,第二句将ListFILES提交到线程池进行处理。接下来的代码:

mExecutor.submit(new Runnable() {@SuppressLint("HandlerLeak")public void run() {List<String> datas;try {datas = mListFileTask.get();} catch (InterruptedException e) {datas = useDefaultData();} catch (ExecutionException e) {datas = useDefaultData();}Message msg = mHandler.obtainMessage(MSG_RECEIVE_TASK_DATA);msg.obj = datas;mHandler.sendMessage(msg);}});
这段代码将一个Runnable提交到线程池执行,mListFileTask.get(); 这句在Callable中的call函数没有执行完之前一直处于阻塞状态(不可以放到主线程中),得到数据后发送消息更新UI。


在init函数中有这么一句:

mShowMulti.setTokenizer(mCustomerToken);
表示使用的是自定义的Tokenizer,他的定义如下
SelfDedineTokenizer mCustomerToken = new SelfDedineTokenizer(';');
这样看到的效果跟图二的就有点不同了哦 ^_^......


3、 完善真个工程,下面滴内容也是不可少滴。也写了几个控件了,看看现在ViewData.java中的内容

package com.xy.zt.selfdefinewieget.data;import java.util.ArrayList;final public class ViewData {public final static ArrayList<ViewData> View_Datas = new ArrayList<ViewData>();public static final int TEXT_VIEW_ID = 90000;public static final String TEXT_VIEW_NAME = "TextView";public static final int BUTTON_ID = TEXT_VIEW_ID + 1;public static final String BUTTON_NAME = "Button";public static final int EDIT_TEXT_ID = BUTTON_ID + 1;public static final String EDIT_TEXT_NAME = "EditText";public static final int AUTO_COMPLETE_TEXTVIEW_ID = EDIT_TEXT_ID + 1;public static final String AUTO_COMPLETE_TEXTVIEW_NAME = "AutoCompleteTextView";public static final int MULTI_AUTO_COMPLETE_TEXTVIEW_ID = AUTO_COMPLETE_TEXTVIEW_ID + 1;public static final String MULTI_AUTO_COMPLETE_TEXTVIEW_NAME = "MultiAutoCompleteTextView";private static final ViewData mTextView = new ViewData(TEXT_VIEW_NAME,TEXT_VIEW_ID);private static final ViewData mButton = new ViewData(BUTTON_NAME, BUTTON_ID);private static final ViewData mEditText = new ViewData(EDIT_TEXT_NAME,EDIT_TEXT_ID);private static final ViewData mAutoCompleteTextView = new ViewData(AUTO_COMPLETE_TEXTVIEW_NAME, AUTO_COMPLETE_TEXTVIEW_ID);private static final ViewData mMultiAutoCompleteTextView = new ViewData(MULTI_AUTO_COMPLETE_TEXTVIEW_NAME, MULTI_AUTO_COMPLETE_TEXTVIEW_ID);public final String mViewName;public final int mViewId;private ViewData(String name, int id) {mViewName = name;mViewId = id;}static {View_Datas.add(mTextView);View_Datas.add(mButton);View_Datas.add(mEditText);View_Datas.add(mAutoCompleteTextView);View_Datas.add(mMultiAutoCompleteTextView);}
}

最后在WidgetsAdapter的handleItemClicked函数中加入如下内容:

case ViewData.MULTI_AUTO_COMPLETE_TEXTVIEW_ID:intent.setClass(mContext, WidgetMultiAutoCompleteActivity.class);mContext.startActivity(intent);break;
handleItemClicked 最新内容如下:

private void handleItemClicked(int action) {Intent intent = new Intent();switch (action) {case ViewData.TEXT_VIEW_ID:intent.setClass(mContext, WidgetTextView.class);mContext.startActivity(intent);break;case ViewData.BUTTON_ID:intent.setClass(mContext, WidgetButtonActivity.class);mContext.startActivity(intent);break;case ViewData.EDIT_TEXT_ID:intent.setClass(mContext, WidgetEditTextActivity.class);mContext.startActivity(intent);break;case ViewData.AUTO_COMPLETE_TEXTVIEW_ID:intent.setClass(mContext, WidgetAutoCompleteActivity.class);mContext.startActivity(intent);break;case ViewData.MULTI_AUTO_COMPLETE_TEXTVIEW_ID:intent.setClass(mContext, WidgetMultiAutoCompleteActivity.class);mContext.startActivity(intent);break;}}

MultiAutoCompleteTextView 就介绍到这里了,下一个控件 Toast 。



这篇关于一步一步学android控件(之六) —— MultiAutoCompleteTextView的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/738322

相关文章

Android中Dialog的使用详解

《Android中Dialog的使用详解》Dialog(对话框)是Android中常用的UI组件,用于临时显示重要信息或获取用户输入,本文给大家介绍Android中Dialog的使用,感兴趣的朋友一起... 目录android中Dialog的使用详解1. 基本Dialog类型1.1 AlertDialog(

Android Kotlin 高阶函数详解及其在协程中的应用小结

《AndroidKotlin高阶函数详解及其在协程中的应用小结》高阶函数是Kotlin中的一个重要特性,它能够将函数作为一等公民(First-ClassCitizen),使得代码更加简洁、灵活和可... 目录1. 引言2. 什么是高阶函数?3. 高阶函数的基础用法3.1 传递函数作为参数3.2 Lambda

Android自定义Scrollbar的两种实现方式

《Android自定义Scrollbar的两种实现方式》本文介绍两种实现自定义滚动条的方法,分别通过ItemDecoration方案和独立View方案实现滚动条定制化,文章通过代码示例讲解的非常详细,... 目录方案一:ItemDecoration实现(推荐用于RecyclerView)实现原理完整代码实现

Android App安装列表获取方法(实践方案)

《AndroidApp安装列表获取方法(实践方案)》文章介绍了Android11及以上版本获取应用列表的方案调整,包括权限配置、白名单配置和action配置三种方式,并提供了相应的Java和Kotl... 目录前言实现方案         方案概述一、 androidManifest 三种配置方式

Android WebView无法加载H5页面的常见问题和解决方法

《AndroidWebView无法加载H5页面的常见问题和解决方法》AndroidWebView是一种视图组件,使得Android应用能够显示网页内容,它基于Chromium,具备现代浏览器的许多功... 目录1. WebView 简介2. 常见问题3. 网络权限设置4. 启用 JavaScript5. D

Android如何获取当前CPU频率和占用率

《Android如何获取当前CPU频率和占用率》最近在优化App的性能,需要获取当前CPU视频频率和占用率,所以本文小编就来和大家总结一下如何在Android中获取当前CPU频率和占用率吧... 最近在优化 App 的性能,需要获取当前 CPU视频频率和占用率,通过查询资料,大致思路如下:目前没有标准的

Android开发中gradle下载缓慢的问题级解决方法

《Android开发中gradle下载缓慢的问题级解决方法》本文介绍了解决Android开发中Gradle下载缓慢问题的几种方法,本文给大家介绍的非常详细,感兴趣的朋友跟随小编一起看看吧... 目录一、网络环境优化二、Gradle版本与配置优化三、其他优化措施针对android开发中Gradle下载缓慢的问

Android 悬浮窗开发示例((动态权限请求 | 前台服务和通知 | 悬浮窗创建 )

《Android悬浮窗开发示例((动态权限请求|前台服务和通知|悬浮窗创建)》本文介绍了Android悬浮窗的实现效果,包括动态权限请求、前台服务和通知的使用,悬浮窗权限需要动态申请并引导... 目录一、悬浮窗 动态权限请求1、动态请求权限2、悬浮窗权限说明3、检查动态权限4、申请动态权限5、权限设置完毕后

Android里面的Service种类以及启动方式

《Android里面的Service种类以及启动方式》Android中的Service分为前台服务和后台服务,前台服务需要亮身份牌并显示通知,后台服务则有启动方式选择,包括startService和b... 目录一句话总结:一、Service 的两种类型:1. 前台服务(必须亮身份牌)2. 后台服务(偷偷干

Android kotlin语言实现删除文件的解决方案

《Androidkotlin语言实现删除文件的解决方案》:本文主要介绍Androidkotlin语言实现删除文件的解决方案,在项目开发过程中,尤其是需要跨平台协作的项目,那么删除用户指定的文件的... 目录一、前言二、适用环境三、模板内容1.权限申请2.Activity中的模板一、前言在项目开发过程中,尤