Filter在AbsListView中的使用
来源:互联网 发布:查看udp端口是否开放 编辑:程序博客网 时间:2024/05/16 10:31
上一篇文章中说到ListAdapter的实现类都实现了Filterable这个接口,这个接口只有一个方法getFilter(),那么这个方法在什么地方被调用的呢?
翻开AbsListView的源码找到了答案。先看下面两段代码
/** * Sets the initial value for the text filter. * @param filterText The text to use for the filter. * * @see #setTextFilterEnabled */ public void setFilterText(String filterText) { // TODO: Should we check for acceptFilter()? if (<span style="color:#ff6600;">mTextFilterEnabled</span> && !TextUtils.isEmpty(filterText)) { createTextFilter(false); // This is going to call our listener onTextChanged, but we might not // be ready to bring up a window yet <span style="color:#ff6600;">mTextFilter.setText(filterText); mTextFilter.setSelection(filterText.length());</span> if (mAdapter instanceof Filterable) { // if mPopup is non-null, then onTextChanged will do the filtering if (mPopup == null) { <span style="color:#ff6600;">Filter f = ((Filterable) mAdapter).getFilter(); f.filter(filterText);</span> } // Set filtered to true so we will display the filter window when our main // window is ready mFiltered = true; mDataSetObserver.clearSavedState(); } } }
/** * For our text watcher that is associated with the text filter. Performs * the actual filtering as the text changes, and takes care of hiding and * showing the popup displaying the currently entered filter text. */ public void onTextChanged(CharSequence s, int start, int before, int count) { if (mPopup != null && <span style="color:#ff6600;">isTextFilterEnabled</span>()) { int length = s.length(); boolean showing = mPopup.isShowing(); if (!showing && length > 0) { // Show the filter popup if necessary showPopup(); mFiltered = true; } else if (showing && length == 0) { // Remove the filter popup if the user has cleared all text dismissPopup(); mFiltered = false; } if (mAdapter instanceof Filterable) { Filter f = ((Filterable) mAdapter).getFilter(); // Filter should not be null when we reach this part if (f != null) { f.filter(s, this); } else { throw new IllegalStateException("You cannot call onTextChanged with a non " + "filterable adapter"); } } } }
从上面的代码可以看到,要使得设置的Filter对象起作用,需要设置mTextFilterEnabled==true,这个设置需要调用方法setTextFilterEnabled(boolean)进行设置。
另外,第一段代码中有个mTextFilter是一个EditText对象,这个对象是AbsListView对象的默认权限元素,当设置了mTextFilterEnabled==true和filterText,这两个值后,就会对ListView的列表元素起过滤作用。
/** * Used with type filter window */ EditText mTextFilter;</span>
以ArrayAdapter为例,执行下面的代码:
ImageView headerView = new ImageView(this); headerView.setImageResource(R.drawable.ic_launcher); listView.addHeaderView(headerView); ImageView footerView = new ImageView(this); footerView.setImageResource(R.drawable.sample); listView.addFooterView(footerView,"hello image view",true); listView.setAdapter(new ArrayAdapter<String>(this,android.R.layout.simple_list_item_checked, new String[]{"孙悟空","猪八戒","沙僧","唐僧","孙悟空","猪八戒","沙僧","唐僧","孙悟空","猪八戒","沙僧","唐僧"})); listView.setOnItemClickListener(new AdapterView.OnItemClickListener() { @Override public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) { Toast.makeText(MyActivity.this, "点击了第" + i + "项", Toast.LENGTH_LONG).show(); } }); listView.setTextFilterEnabled(true); listView.setFilterText("孙悟空");
执行结果如下图所示,显示了mTextFilter对象,并且过滤掉所有不包含filterText--“孙悟空”的所有列表项,如果不需要过滤可以调用clearTextFilter()方法。ArrayAdapter的Filter类动作定义见上一篇文章最后贴出的代码。
另外,代码里调用了filter(CharSequence)和filter(CharSequence, FilterListener)两个方法,这两个方法是在抽象类Filter中实现的,Filter抽象类的源码在下面贴出来作为参考:
/* * Copyright (C) 2007 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */package android.widget;import android.os.Handler;import android.os.HandlerThread;import android.os.Looper;import android.os.Message;import android.util.Log;/** * <p>A filter constrains data with a filtering pattern.</p> * * <p>Filters are usually created by {@link android.widget.Filterable} * classes.</p> * * <p>Filtering operations performed by calling {@link #filter(CharSequence)} or * {@link #filter(CharSequence, android.widget.Filter.FilterListener)} are * performed asynchronously. When these methods are called, a filtering request * is posted in a request queue and processed later. Any call to one of these * methods will cancel any previous non-executed filtering request.</p> * * @see android.widget.Filterable */public abstract class Filter { private static final String LOG_TAG = "Filter"; private static final String THREAD_NAME = "Filter"; private static final int FILTER_TOKEN = 0xD0D0F00D; private static final int FINISH_TOKEN = 0xDEADBEEF; private Handler mThreadHandler; private Handler mResultHandler; private Delayer mDelayer; private final Object mLock = new Object(); /** * <p>Creates a new asynchronous filter.</p> */ public Filter() { mResultHandler = new ResultsHandler(); } /** * Provide an interface that decides how long to delay the message for a given query. Useful * for heuristics such as posting a delay for the delete key to avoid doing any work while the * user holds down the delete key. * * @param delayer The delayer. * @hide */ public void setDelayer(Delayer delayer) { synchronized (mLock) { mDelayer = delayer; } } /** * <p>Starts an asynchronous filtering operation. Calling this method * cancels all previous non-executed filtering requests and posts a new * filtering request that will be executed later.</p> * * @param constraint the constraint used to filter the data * * @see #filter(CharSequence, android.widget.Filter.FilterListener) */ public final void filter(CharSequence constraint) { filter(constraint, null); } /** * <p>Starts an asynchronous filtering operation. Calling this method * cancels all previous non-executed filtering requests and posts a new * filtering request that will be executed later.</p> * * <p>Upon completion, the listener is notified.</p> * * @param constraint the constraint used to filter the data * @param listener a listener notified upon completion of the operation * * @see #filter(CharSequence) * @see #performFiltering(CharSequence) * @see #publishResults(CharSequence, android.widget.Filter.FilterResults) */ public final void filter(CharSequence constraint, FilterListener listener) { synchronized (mLock) { if (mThreadHandler == null) { HandlerThread thread = new HandlerThread( THREAD_NAME, android.os.Process.THREAD_PRIORITY_BACKGROUND); thread.start(); mThreadHandler = new RequestHandler(thread.getLooper()); } final long delay = (mDelayer == null) ? 0 : mDelayer.getPostingDelay(constraint); Message message = mThreadHandler.obtainMessage(FILTER_TOKEN); RequestArguments args = new RequestArguments(); // make sure we use an immutable copy of the constraint, so that // it doesn't change while the filter operation is in progress args.constraint = constraint != null ? constraint.toString() : null; args.listener = listener; message.obj = args; mThreadHandler.removeMessages(FILTER_TOKEN); mThreadHandler.removeMessages(FINISH_TOKEN); mThreadHandler.sendMessageDelayed(message, delay); } } /** * <p>Invoked in a worker thread to filter the data according to the * constraint. Subclasses must implement this method to perform the * filtering operation. Results computed by the filtering operation * must be returned as a {@link android.widget.Filter.FilterResults} that * will then be published in the UI thread through * {@link #publishResults(CharSequence, * android.widget.Filter.FilterResults)}.</p> * * <p><strong>Contract:</strong> When the constraint is null, the original * data must be restored.</p> * * @param constraint the constraint used to filter the data * @return the results of the filtering operation * * @see #filter(CharSequence, android.widget.Filter.FilterListener) * @see #publishResults(CharSequence, android.widget.Filter.FilterResults) * @see android.widget.Filter.FilterResults */ protected abstract FilterResults performFiltering(CharSequence constraint); /** * <p>Invoked in the UI thread to publish the filtering results in the * user interface. Subclasses must implement this method to display the * results computed in {@link #performFiltering}.</p> * * @param constraint the constraint used to filter the data * @param results the results of the filtering operation * * @see #filter(CharSequence, android.widget.Filter.FilterListener) * @see #performFiltering(CharSequence) * @see android.widget.Filter.FilterResults */ protected abstract void publishResults(CharSequence constraint, FilterResults results); /** * <p>Converts a value from the filtered set into a CharSequence. Subclasses * should override this method to convert their results. The default * implementation returns an empty String for null values or the default * String representation of the value.</p> * * @param resultValue the value to convert to a CharSequence * @return a CharSequence representing the value */ public CharSequence convertResultToString(Object resultValue) { return resultValue == null ? "" : resultValue.toString(); } /** * <p>Holds the results of a filtering operation. The results are the values * computed by the filtering operation and the number of these values.</p> */ protected static class FilterResults { public FilterResults() { // nothing to see here } /** * <p>Contains all the values computed by the filtering operation.</p> */ public Object values; /** * <p>Contains the number of values computed by the filtering * operation.</p> */ public int count; } /** * <p>Listener used to receive a notification upon completion of a filtering * operation.</p> */ public static interface FilterListener { /** * <p>Notifies the end of a filtering operation.</p> * * @param count the number of values computed by the filter */ public void onFilterComplete(int count); } /** * <p>Worker thread handler. When a new filtering request is posted from * {@link android.widget.Filter#filter(CharSequence, android.widget.Filter.FilterListener)}, * it is sent to this handler.</p> */ private class RequestHandler extends Handler { public RequestHandler(Looper looper) { super(looper); } /** * <p>Handles filtering requests by calling * {@link Filter#performFiltering} and then sending a message * with the results to the results handler.</p> * * @param msg the filtering request */ public void handleMessage(Message msg) { int what = msg.what; Message message; switch (what) { case FILTER_TOKEN: RequestArguments args = (RequestArguments) msg.obj; try { args.results = performFiltering(args.constraint); } catch (Exception e) { args.results = new FilterResults(); Log.w(LOG_TAG, "An exception occured during performFiltering()!", e); } finally { message = mResultHandler.obtainMessage(what); message.obj = args; message.sendToTarget(); } synchronized (mLock) { if (mThreadHandler != null) { Message finishMessage = mThreadHandler.obtainMessage(FINISH_TOKEN); mThreadHandler.sendMessageDelayed(finishMessage, 3000); } } break; case FINISH_TOKEN: synchronized (mLock) { if (mThreadHandler != null) { mThreadHandler.getLooper().quit(); mThreadHandler = null; } } break; } } } /** * <p>Handles the results of a filtering operation. The results are * handled in the UI thread.</p> */ private class ResultsHandler extends Handler { /** * <p>Messages received from the request handler are processed in the * UI thread. The processing involves calling * {@link Filter#publishResults(CharSequence, * android.widget.Filter.FilterResults)} * to post the results back in the UI and then notifying the listener, * if any.</p> * * @param msg the filtering results */ @Override public void handleMessage(Message msg) { RequestArguments args = (RequestArguments) msg.obj; publishResults(args.constraint, args.results); if (args.listener != null) { int count = args.results != null ? args.results.count : -1; args.listener.onFilterComplete(count); } } } /** * <p>Holds the arguments of a filtering request as well as the results * of the request.</p> */ private static class RequestArguments { /** * <p>The constraint used to filter the data.</p> */ CharSequence constraint; /** * <p>The listener to notify upon completion. Can be null.</p> */ FilterListener listener; /** * <p>The results of the filtering operation.</p> */ FilterResults results; } /** * @hide */ public interface Delayer { /** * @param constraint The constraint passed to {@link Filter#filter(CharSequence)} * @return The delay that should be used for * {@link Handler#sendMessageDelayed(android.os.Message, long)} */ long getPostingDelay(CharSequence constraint); }}
0 0
- Filter在AbsListView中的使用
- kalman filter在倾角传感器中的使用
- HttpServletRequestWrapper,HttpServletResponseWrapper在过滤器Filter中的使用
- 过滤器[登录+编码]filter在程序中的使用
- 过滤器[登录+编码]filter在程序中的使用
- Servlet中的filter使用
- Android中的Filter使用
- css3 中的filter使用
- View 和 AbsListView中的onSaveInstanceState()方法以及onRestoreInstanceState()方法的使用
- j2ee中的过滤器Filter使用
- Android中的Intent filter使用
- Web开发中的Filter使用
- 详细讲解Android中的AbsListView的源码
- android AbsListView之ListView使用(1)
- android AbsListView之ListView使用(2)-BaseAdapter
- 谈Filter在网页中的运用
- Filter在web.xml中的配置顺序
- Filter在Web开发中的应用
- 正则表达式学习
- 关于ListView设置了OnScrollListener之后onScrollStateChanged()和onScroll方法监听不到的问题
- comparator接口与Comparable接口的区别
- limux下进度条代码
- 内存分析工具 MAT 的使用
- Filter在AbsListView中的使用
- cxFreeze安装程序制作
- scanner:java的scanner类详解
- 二叉树的前序,中序及后续遍历
- 数据库调优教程(四)Explain性能分析命令
- House Robber
- 七种qsort的写法
- 匿名管道-实例
- Ext.Net 后台主页布局