• 一步一步学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" >
    
        <MultiAutoCompleteTextView
            android: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")
            @Override
            public 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;
                }
                ;
            }
    
        };
    
        @Override
        public 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;
        }
    
        @Override
        protected 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 。



  • 相关阅读:
    字符串最大最小表示法模板 ( 字典序最大最小 )
    Manacher模板( 线性求最长回文子串 )
    2017南宁网络赛 Problem J Minimum Distance in a Star Graph ( 模拟 )
    字符串截取模板 && POJ 3450、3080 ( 暴力枚举子串 && KMP匹配 )
    HDU 6153 A Secret ( KMP&&DP || 拓展KMP )
    51Nod 1277 字符串中的最大值 ( KMP && DP )
    HDU 4300 Clairewd's message ( 拓展KMP )
    拓展KMP以及模板
    KMP解决字符串最小循环节相关问题
    序列终结者 BZOJ 1251 Splay
  • 原文地址:https://www.cnblogs.com/pangblog/p/3402550.html
Copyright © 2020-2023  润新知