blob: 027f6d6f27272ab958be825d285d8bb39ac3648c [file] [log] [blame]
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001/*
2 * Copyright (C) 2006 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package android.widget;
18
Tor Norbye7b9c9122013-05-30 16:48:33 -070019import android.annotation.ArrayRes;
20import android.annotation.IdRes;
21import android.annotation.LayoutRes;
Tor Norbye417ee5b2015-03-10 20:57:37 -070022import android.annotation.NonNull;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080023import android.content.Context;
Alan Viveretteb9ead4a2015-01-14 10:43:31 -080024import android.content.res.Resources;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080025import android.util.Log;
Alan Viveretteb9ead4a2015-01-14 10:43:31 -080026import android.view.ContextThemeWrapper;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080027import android.view.LayoutInflater;
28import android.view.View;
29import android.view.ViewGroup;
30
31import java.util.ArrayList;
32import java.util.Arrays;
Christian Mehlmauer8c582ef2010-06-11 22:28:38 +020033import java.util.Collection;
The Android Open Source Projectc39a6e02009-03-11 12:11:56 -070034import java.util.Collections;
Gilles Debunnebe2c4f92011-01-17 15:14:32 -080035import java.util.Comparator;
36import java.util.List;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080037
38/**
Dianne Hackbornb1ad5972010-08-02 17:30:33 -070039 * A concrete BaseAdapter that is backed by an array of arbitrary
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080040 * objects. By default this class expects that the provided resource id references
41 * a single TextView. If you want to use a more complex layout, use the constructors that
42 * also takes a field id. That field id should reference a TextView in the larger layout
43 * resource.
44 *
Dianne Hackbornb1ad5972010-08-02 17:30:33 -070045 * <p>However the TextView is referenced, it will be filled with the toString() of each object in
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080046 * the array. You can add lists or arrays of custom objects. Override the toString() method
47 * of your objects to determine what text will be displayed for the item in the list.
48 *
Dianne Hackbornb1ad5972010-08-02 17:30:33 -070049 * <p>To use something other than TextViews for the array display, for instance, ImageViews,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080050 * or to have some of data besides toString() results fill the views,
51 * override {@link #getView(int, View, ViewGroup)} to return the type of view you want.
52 */
Alan Viverette2add9bc2015-06-02 14:54:40 -070053public class ArrayAdapter<T> extends BaseAdapter implements Filterable, ThemedSpinnerAdapter {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080054 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080055 * Lock used to modify the content of {@link #mObjects}. Any write operation
56 * performed on the array should be synchronized on this lock. This lock is also
57 * used by the filter (see {@link #getFilter()} to make a synchronized copy of
58 * the original array of data.
59 */
60 private final Object mLock = new Object();
61
Alan Viverette7d5967e2015-06-03 16:27:36 -070062 private final LayoutInflater mInflater;
63
64 /**
65 * Contains the list of objects that represent the data of this ArrayAdapter.
66 * The content of this list is referred to as "the array" in the documentation.
67 */
68 private List<T> mObjects;
69
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080070 /**
71 * The resource indicating what views to inflate to display the content of this
72 * array adapter.
73 */
74 private int mResource;
75
76 /**
77 * The resource indicating what views to inflate to display the content of this
78 * array adapter in a drop down widget.
79 */
80 private int mDropDownResource;
81
82 /**
83 * If the inflated resource is not a TextView, {@link #mFieldId} is used to find
84 * a TextView inside the inflated views hierarchy. This field must contain the
85 * identifier that matches the one defined in the resource file.
86 */
87 private int mFieldId = 0;
88
89 /**
90 * Indicates whether or not {@link #notifyDataSetChanged()} must be called whenever
91 * {@link #mObjects} is modified.
92 */
93 private boolean mNotifyOnChange = true;
94
Christian Mehlmauer8c582ef2010-06-11 22:28:38 +020095 private Context mContext;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080096
Gilles Debunnebe2c4f92011-01-17 15:14:32 -080097 // A copy of the original mObjects array, initialized from and then used instead as soon as
98 // the mFilter ArrayFilter is used. mObjects will then only contain the filtered values.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080099 private ArrayList<T> mOriginalValues;
100 private ArrayFilter mFilter;
101
Alan Viveretteb9ead4a2015-01-14 10:43:31 -0800102 /** Layout inflater used for {@link #getDropDownView(int, View, ViewGroup)}. */
103 private LayoutInflater mDropDownInflater;
104
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800105 /**
106 * Constructor
107 *
108 * @param context The current context.
Romain Guy9c5d1b12013-01-09 20:16:37 -0800109 * @param resource The resource ID for a layout file containing a TextView to use when
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800110 * instantiating views.
111 */
Tor Norbye7b9c9122013-05-30 16:48:33 -0700112 public ArrayAdapter(Context context, @LayoutRes int resource) {
Alan Viveretteb9ead4a2015-01-14 10:43:31 -0800113 this(context, resource, 0, new ArrayList<T>());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800114 }
115
116 /**
117 * Constructor
118 *
119 * @param context The current context.
120 * @param resource The resource ID for a layout file containing a layout to use when
121 * instantiating views.
122 * @param textViewResourceId The id of the TextView within the layout resource to be populated
123 */
Tor Norbye7b9c9122013-05-30 16:48:33 -0700124 public ArrayAdapter(Context context, @LayoutRes int resource, @IdRes int textViewResourceId) {
Alan Viveretteb9ead4a2015-01-14 10:43:31 -0800125 this(context, resource, textViewResourceId, new ArrayList<T>());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800126 }
127
128 /**
129 * Constructor
130 *
131 * @param context The current context.
Romain Guy9c5d1b12013-01-09 20:16:37 -0800132 * @param resource The resource ID for a layout file containing a TextView to use when
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800133 * instantiating views.
134 * @param objects The objects to represent in the ListView.
135 */
Tor Norbye417ee5b2015-03-10 20:57:37 -0700136 public ArrayAdapter(Context context, @LayoutRes int resource, @NonNull T[] objects) {
Alan Viveretteb9ead4a2015-01-14 10:43:31 -0800137 this(context, resource, 0, Arrays.asList(objects));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800138 }
139
140 /**
141 * Constructor
142 *
143 * @param context The current context.
144 * @param resource The resource ID for a layout file containing a layout to use when
145 * instantiating views.
146 * @param textViewResourceId The id of the TextView within the layout resource to be populated
147 * @param objects The objects to represent in the ListView.
148 */
Tor Norbye417ee5b2015-03-10 20:57:37 -0700149 public ArrayAdapter(Context context, @LayoutRes int resource, @IdRes int textViewResourceId,
150 @NonNull T[] objects) {
Alan Viveretteb9ead4a2015-01-14 10:43:31 -0800151 this(context, resource, textViewResourceId, Arrays.asList(objects));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800152 }
153
154 /**
155 * Constructor
156 *
157 * @param context The current context.
Romain Guy9c5d1b12013-01-09 20:16:37 -0800158 * @param resource The resource ID for a layout file containing a TextView to use when
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800159 * instantiating views.
160 * @param objects The objects to represent in the ListView.
161 */
Tor Norbye417ee5b2015-03-10 20:57:37 -0700162 public ArrayAdapter(Context context, @LayoutRes int resource, @NonNull List<T> objects) {
Alan Viveretteb9ead4a2015-01-14 10:43:31 -0800163 this(context, resource, 0, objects);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800164 }
165
166 /**
167 * Constructor
168 *
169 * @param context The current context.
170 * @param resource The resource ID for a layout file containing a layout to use when
171 * instantiating views.
172 * @param textViewResourceId The id of the TextView within the layout resource to be populated
173 * @param objects The objects to represent in the ListView.
174 */
Tor Norbye417ee5b2015-03-10 20:57:37 -0700175 public ArrayAdapter(Context context, @LayoutRes int resource, @IdRes int textViewResourceId,
176 @NonNull List<T> objects) {
Alan Viveretteb9ead4a2015-01-14 10:43:31 -0800177 mContext = context;
178 mInflater = LayoutInflater.from(context);
179 mResource = mDropDownResource = resource;
180 mObjects = objects;
181 mFieldId = textViewResourceId;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800182 }
183
184 /**
185 * Adds the specified object at the end of the array.
186 *
187 * @param object The object to add at the end of the array.
188 */
189 public void add(T object) {
Gilles Debunnebe2c4f92011-01-17 15:14:32 -0800190 synchronized (mLock) {
191 if (mOriginalValues != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800192 mOriginalValues.add(object);
Gilles Debunnebe2c4f92011-01-17 15:14:32 -0800193 } else {
194 mObjects.add(object);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800195 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800196 }
Gilles Debunnebe2c4f92011-01-17 15:14:32 -0800197 if (mNotifyOnChange) notifyDataSetChanged();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800198 }
199
200 /**
Christian Mehlmauer8c582ef2010-06-11 22:28:38 +0200201 * Adds the specified Collection at the end of the array.
202 *
203 * @param collection The Collection to add at the end of the array.
204 */
205 public void addAll(Collection<? extends T> collection) {
Gilles Debunnebe2c4f92011-01-17 15:14:32 -0800206 synchronized (mLock) {
207 if (mOriginalValues != null) {
Christian Mehlmauer8c582ef2010-06-11 22:28:38 +0200208 mOriginalValues.addAll(collection);
Gilles Debunnebe2c4f92011-01-17 15:14:32 -0800209 } else {
210 mObjects.addAll(collection);
Christian Mehlmauer8c582ef2010-06-11 22:28:38 +0200211 }
Christian Mehlmauer8c582ef2010-06-11 22:28:38 +0200212 }
Gilles Debunnebe2c4f92011-01-17 15:14:32 -0800213 if (mNotifyOnChange) notifyDataSetChanged();
Christian Mehlmauer8c582ef2010-06-11 22:28:38 +0200214 }
215
216 /**
217 * Adds the specified items at the end of the array.
218 *
219 * @param items The items to add at the end of the array.
220 */
221 public void addAll(T ... items) {
Gilles Debunnebe2c4f92011-01-17 15:14:32 -0800222 synchronized (mLock) {
223 if (mOriginalValues != null) {
Romain Guy95a78c32011-08-15 15:36:30 -0700224 Collections.addAll(mOriginalValues, items);
Gilles Debunnebe2c4f92011-01-17 15:14:32 -0800225 } else {
Romain Guy95a78c32011-08-15 15:36:30 -0700226 Collections.addAll(mObjects, items);
Christian Mehlmauer8c582ef2010-06-11 22:28:38 +0200227 }
Christian Mehlmauer8c582ef2010-06-11 22:28:38 +0200228 }
Gilles Debunnebe2c4f92011-01-17 15:14:32 -0800229 if (mNotifyOnChange) notifyDataSetChanged();
Christian Mehlmauer8c582ef2010-06-11 22:28:38 +0200230 }
231
232 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800233 * Inserts the specified object at the specified index in the array.
234 *
235 * @param object The object to insert into the array.
236 * @param index The index at which the object must be inserted.
237 */
238 public void insert(T object, int index) {
Gilles Debunnebe2c4f92011-01-17 15:14:32 -0800239 synchronized (mLock) {
240 if (mOriginalValues != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800241 mOriginalValues.add(index, object);
Gilles Debunnebe2c4f92011-01-17 15:14:32 -0800242 } else {
243 mObjects.add(index, object);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800244 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800245 }
Gilles Debunnebe2c4f92011-01-17 15:14:32 -0800246 if (mNotifyOnChange) notifyDataSetChanged();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800247 }
248
249 /**
250 * Removes the specified object from the array.
251 *
252 * @param object The object to remove.
253 */
254 public void remove(T object) {
Gilles Debunnebe2c4f92011-01-17 15:14:32 -0800255 synchronized (mLock) {
256 if (mOriginalValues != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800257 mOriginalValues.remove(object);
Gilles Debunnebe2c4f92011-01-17 15:14:32 -0800258 } else {
259 mObjects.remove(object);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800260 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800261 }
262 if (mNotifyOnChange) notifyDataSetChanged();
263 }
264
265 /**
266 * Remove all elements from the list.
267 */
268 public void clear() {
Gilles Debunnebe2c4f92011-01-17 15:14:32 -0800269 synchronized (mLock) {
270 if (mOriginalValues != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800271 mOriginalValues.clear();
Gilles Debunnebe2c4f92011-01-17 15:14:32 -0800272 } else {
273 mObjects.clear();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800274 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800275 }
276 if (mNotifyOnChange) notifyDataSetChanged();
277 }
278
279 /**
The Android Open Source Projectc39a6e02009-03-11 12:11:56 -0700280 * Sorts the content of this adapter using the specified comparator.
281 *
282 * @param comparator The comparator used to sort the objects contained
283 * in this adapter.
284 */
285 public void sort(Comparator<? super T> comparator) {
Gilles Debunnebe2c4f92011-01-17 15:14:32 -0800286 synchronized (mLock) {
287 if (mOriginalValues != null) {
288 Collections.sort(mOriginalValues, comparator);
289 } else {
290 Collections.sort(mObjects, comparator);
291 }
292 }
Christian Mehlmauer8c582ef2010-06-11 22:28:38 +0200293 if (mNotifyOnChange) notifyDataSetChanged();
The Android Open Source Projectc39a6e02009-03-11 12:11:56 -0700294 }
295
296 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800297 * {@inheritDoc}
298 */
299 @Override
300 public void notifyDataSetChanged() {
301 super.notifyDataSetChanged();
302 mNotifyOnChange = true;
303 }
304
305 /**
306 * Control whether methods that change the list ({@link #add},
307 * {@link #insert}, {@link #remove}, {@link #clear}) automatically call
308 * {@link #notifyDataSetChanged}. If set to false, caller must
309 * manually call notifyDataSetChanged() to have the changes
310 * reflected in the attached view.
311 *
312 * The default is true, and calling notifyDataSetChanged()
313 * resets the flag to true.
314 *
315 * @param notifyOnChange if true, modifications to the list will
316 * automatically call {@link
317 * #notifyDataSetChanged}
318 */
319 public void setNotifyOnChange(boolean notifyOnChange) {
320 mNotifyOnChange = notifyOnChange;
321 }
322
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800323 /**
324 * Returns the context associated with this array adapter. The context is used
325 * to create views from the resource passed to the constructor.
326 *
327 * @return The Context associated with this adapter.
328 */
329 public Context getContext() {
330 return mContext;
331 }
332
333 /**
334 * {@inheritDoc}
335 */
336 public int getCount() {
337 return mObjects.size();
338 }
339
340 /**
341 * {@inheritDoc}
342 */
343 public T getItem(int position) {
344 return mObjects.get(position);
345 }
346
347 /**
348 * Returns the position of the specified item in the array.
349 *
350 * @param item The item to retrieve the position of.
351 *
352 * @return The position of the specified item.
353 */
354 public int getPosition(T item) {
355 return mObjects.indexOf(item);
356 }
357
358 /**
359 * {@inheritDoc}
360 */
361 public long getItemId(int position) {
362 return position;
363 }
364
365 /**
366 * {@inheritDoc}
367 */
368 public View getView(int position, View convertView, ViewGroup parent) {
Alan Viveretteb9ead4a2015-01-14 10:43:31 -0800369 return createViewFromResource(mInflater, position, convertView, parent, mResource);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800370 }
371
Alan Viveretteb9ead4a2015-01-14 10:43:31 -0800372 private View createViewFromResource(LayoutInflater inflater, int position, View convertView,
373 ViewGroup parent, int resource) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800374 View view;
375 TextView text;
376
377 if (convertView == null) {
Alan Viveretteb9ead4a2015-01-14 10:43:31 -0800378 view = inflater.inflate(resource, parent, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800379 } else {
380 view = convertView;
381 }
382
383 try {
384 if (mFieldId == 0) {
385 // If no custom field is assigned, assume the whole resource is a TextView
386 text = (TextView) view;
387 } else {
388 // Otherwise, find the TextView field within the layout
389 text = (TextView) view.findViewById(mFieldId);
390 }
391 } catch (ClassCastException e) {
392 Log.e("ArrayAdapter", "You must supply a resource ID for a TextView");
393 throw new IllegalStateException(
394 "ArrayAdapter requires the resource ID to be a TextView", e);
395 }
396
Daisuke Miyakawab5d91322009-07-09 14:26:56 +0900397 T item = getItem(position);
398 if (item instanceof CharSequence) {
399 text.setText((CharSequence)item);
400 } else {
401 text.setText(item.toString());
402 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800403
404 return view;
405 }
406
407 /**
408 * <p>Sets the layout resource to create the drop down views.</p>
409 *
410 * @param resource the layout resource defining the drop down views
411 * @see #getDropDownView(int, android.view.View, android.view.ViewGroup)
412 */
Tor Norbye7b9c9122013-05-30 16:48:33 -0700413 public void setDropDownViewResource(@LayoutRes int resource) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800414 this.mDropDownResource = resource;
415 }
416
417 /**
Alan Viveretteb9ead4a2015-01-14 10:43:31 -0800418 * Sets the {@link Resources.Theme} against which drop-down views are
419 * inflated.
420 * <p>
421 * By default, drop-down views are inflated against the theme of the
422 * {@link Context} passed to the adapter's constructor.
423 *
424 * @param theme the theme against which to inflate drop-down views or
425 * {@code null} to use the theme from the adapter's context
426 * @see #getDropDownView(int, View, ViewGroup)
427 */
428 @Override
429 public void setDropDownViewTheme(Resources.Theme theme) {
430 if (theme == null) {
431 mDropDownInflater = null;
432 } else if (theme == mInflater.getContext().getTheme()) {
433 mDropDownInflater = mInflater;
434 } else {
435 final Context context = new ContextThemeWrapper(mContext, theme);
436 mDropDownInflater = LayoutInflater.from(context);
437 }
438 }
439
440 @Override
441 public Resources.Theme getDropDownViewTheme() {
442 return mDropDownInflater == null ? null : mDropDownInflater.getContext().getTheme();
443 }
444
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800445 @Override
446 public View getDropDownView(int position, View convertView, ViewGroup parent) {
Alan Viveretteb9ead4a2015-01-14 10:43:31 -0800447 final LayoutInflater inflater = mDropDownInflater == null ? mInflater : mDropDownInflater;
448 return createViewFromResource(inflater, position, convertView, parent, mDropDownResource);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800449 }
450
451 /**
452 * Creates a new ArrayAdapter from external resources. The content of the array is
453 * obtained through {@link android.content.res.Resources#getTextArray(int)}.
454 *
455 * @param context The application's environment.
456 * @param textArrayResId The identifier of the array to use as the data source.
457 * @param textViewResId The identifier of the layout used to create views.
458 *
459 * @return An ArrayAdapter<CharSequence>.
460 */
461 public static ArrayAdapter<CharSequence> createFromResource(Context context,
Tor Norbye7b9c9122013-05-30 16:48:33 -0700462 @ArrayRes int textArrayResId, @LayoutRes int textViewResId) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800463 CharSequence[] strings = context.getResources().getTextArray(textArrayResId);
464 return new ArrayAdapter<CharSequence>(context, textViewResId, strings);
465 }
466
467 /**
468 * {@inheritDoc}
469 */
470 public Filter getFilter() {
471 if (mFilter == null) {
472 mFilter = new ArrayFilter();
473 }
474 return mFilter;
475 }
476
477 /**
478 * <p>An array filter constrains the content of the array adapter with
479 * a prefix. Each item that does not start with the supplied prefix
480 * is removed from the list.</p>
481 */
482 private class ArrayFilter extends Filter {
483 @Override
484 protected FilterResults performFiltering(CharSequence prefix) {
485 FilterResults results = new FilterResults();
486
487 if (mOriginalValues == null) {
488 synchronized (mLock) {
489 mOriginalValues = new ArrayList<T>(mObjects);
490 }
491 }
492
493 if (prefix == null || prefix.length() == 0) {
Romain Guy95a78c32011-08-15 15:36:30 -0700494 ArrayList<T> list;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800495 synchronized (mLock) {
Romain Guy95a78c32011-08-15 15:36:30 -0700496 list = new ArrayList<T>(mOriginalValues);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800497 }
Romain Guy95a78c32011-08-15 15:36:30 -0700498 results.values = list;
499 results.count = list.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800500 } else {
501 String prefixString = prefix.toString().toLowerCase();
502
Romain Guy95a78c32011-08-15 15:36:30 -0700503 ArrayList<T> values;
504 synchronized (mLock) {
505 values = new ArrayList<T>(mOriginalValues);
506 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800507
Romain Guy95a78c32011-08-15 15:36:30 -0700508 final int count = values.size();
509 final ArrayList<T> newValues = new ArrayList<T>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800510
511 for (int i = 0; i < count; i++) {
512 final T value = values.get(i);
513 final String valueText = value.toString().toLowerCase();
514
515 // First match against the whole, non-splitted value
516 if (valueText.startsWith(prefixString)) {
517 newValues.add(value);
518 } else {
519 final String[] words = valueText.split(" ");
520 final int wordCount = words.length;
521
Gilles Debunnebe2c4f92011-01-17 15:14:32 -0800522 // Start at index 0, in case valueText starts with space(s)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800523 for (int k = 0; k < wordCount; k++) {
524 if (words[k].startsWith(prefixString)) {
525 newValues.add(value);
526 break;
527 }
528 }
529 }
530 }
531
532 results.values = newValues;
533 results.count = newValues.size();
534 }
535
536 return results;
537 }
538
539 @Override
540 protected void publishResults(CharSequence constraint, FilterResults results) {
541 //noinspection unchecked
542 mObjects = (List<T>) results.values;
543 if (results.count > 0) {
544 notifyDataSetChanged();
545 } else {
546 notifyDataSetInvalidated();
547 }
548 }
549 }
550}