AI2 Component  (Version nb184)
ListView.java
Go to the documentation of this file.
1 // -*- mode: java; c-basic-offset: 2; -*-
2 // Copyright 2009-2011 Google, All Rights reserved
3 // Copyright 2011-2020 MIT, All rights reserved
4 // Released under the Apache License, Version 2.0
5 // http://www.apache.org/licenses/LICENSE-2.0
6 
7 package com.google.appinventor.components.runtime;
8 
9 import android.graphics.Color;
10 import android.graphics.drawable.ColorDrawable;
11 import android.graphics.drawable.Drawable;
12 import android.graphics.drawable.GradientDrawable;
13 import android.graphics.drawable.StateListDrawable;
14 import android.text.Editable;
15 import android.text.Spannable;
16 import android.text.SpannableString;
17 import android.text.TextWatcher;
18 import android.text.style.AbsoluteSizeSpan;
19 import android.text.style.ForegroundColorSpan;
20 import android.view.View;
21 import android.view.ViewGroup;
22 import android.widget.AbsListView;
23 import android.widget.AdapterView;
24 import android.widget.ArrayAdapter;
25 import android.widget.EditText;
26 import android.widget.LinearLayout;
27 
28 import android.widget.LinearLayout.LayoutParams;
41 
56 @DesignerComponent(version = YaVersion.LISTVIEW_COMPONENT_VERSION,
57  description = "<p>This is a visible component that displays a list of text elements." +
58  " <br> The list can be set using the ElementsFromString property" +
59  " or using the Elements block in the blocks editor. </p>",
60  category = ComponentCategory.USERINTERFACE,
61  nonVisible = false,
62  iconName = "images/listView.png")
63 @SimpleObject
64 public final class ListView extends AndroidViewComponent implements AdapterView.OnItemClickListener,
65  AdapterView.OnItemSelectedListener {
66 
67  private static final String LOG_TAG = "ListView";
68 
69  private final android.widget.ListView view;
70  private EditText txtSearchBox;
71  protected final ComponentContainer container;
72  private final LinearLayout listViewLayout;
73 
74  // The adapter contains spannables rather than strings, since we will be changing the item
75  // colors using ForegroundColorSpan
76  private ArrayAdapter<Spannable> adapter;
77  private ArrayAdapter<Spannable> adapterCopy;
78  private YailList items;
79  private int selectionIndex;
80  private String selection;
81  private boolean showFilter = false;
82  private static final boolean DEFAULT_ENABLED = false;
83 
84  private int backgroundColor;
85  private static final int DEFAULT_BACKGROUND_COLOR = Component.COLOR_BLACK;
86 
87  // The text color of the ListView's items. All items have the same text color
88  private int textColor;
89  private static final int DEFAULT_TEXT_COLOR = Component.COLOR_WHITE;
90 
91  private int selectionColor;
92  private static final int DEFAULT_SELECTION_COLOR = Component.COLOR_LTGRAY;
93  private static final Drawable UNSELECTED_DRAWABLE = new ColorDrawable(Color.TRANSPARENT);
94 
95  private Drawable selectionDrawable;
96  private View lastSelected;
97 
98  private int textSize;
99  private static final int DEFAULT_TEXT_SIZE = 22;
100 
106  super(container);
107  this.container = container;
108  items = YailList.makeEmptyList();
109  // initialize selectionIndex which also sets selection
110  SelectionIndex(0);
111  view = new android.widget.ListView(container.$context());
112  view.setOnItemClickListener(this);
113  view.setOnItemSelectedListener(this);
114  view.setChoiceMode(android.widget.ListView.CHOICE_MODE_SINGLE);
115  view.setScrollingCacheEnabled(false);
116  view.setSelector(new StateListDrawable()); // Set to empty selector to prevent issues with dynamic highlighting
117  listViewLayout = new LinearLayout(container.$context());
118  listViewLayout.setOrientation(LinearLayout.VERTICAL);
119 
120  txtSearchBox = new EditText(container.$context());
121  txtSearchBox.setSingleLine(true);
122  txtSearchBox.setWidth(Component.LENGTH_FILL_PARENT);
123  txtSearchBox.setPadding(10, 10, 10, 10);
124  txtSearchBox.setHint("Search list...");
126  txtSearchBox.setBackgroundColor(Color.WHITE);
127  }
128 
129  //set up the listener
130  txtSearchBox.addTextChangedListener(new TextWatcher() {
131 
132  @Override
133  public void onTextChanged(CharSequence cs, int arg1, int arg2, int arg3) {
134  // When user changed the Text
135  adapter.getFilter().filter(cs);
136  }
137 
138  @Override
139  public void beforeTextChanged(CharSequence arg0, int arg1, int arg2, int arg3) {
140  // no-op. Required method
141  }
142 
143  @Override
144  public void afterTextChanged(Editable arg0) {
145  // no-op. Required method
146  }
147  });
148 
149  if (showFilter) {
150  txtSearchBox.setVisibility(View.VISIBLE);
151  } else {
152  txtSearchBox.setVisibility(View.GONE);
153  }
154 
155  // set the colors and initialize the elements
156  // note that the TextColor and ElementsFromString setters
157  // need to have the textColor set first, since they reset the
158  // adapter
159 
161  BackgroundColor(DEFAULT_BACKGROUND_COLOR);
162  SelectionColor(DEFAULT_SELECTION_COLOR);
163 
164  textColor = DEFAULT_TEXT_COLOR;
165  TextColor(textColor);
166  textSize = DEFAULT_TEXT_SIZE;
167  TextSize(textSize);
168  ElementsFromString("");
169 
170  listViewLayout.addView(txtSearchBox);
171  listViewLayout.addView(view);
172  listViewLayout.requestLayout();
173  container.$add(this);
174  };
175 
176  @Override
177  public View getView() {
178  return listViewLayout;
179  }
180 
185  @Override
186  @SimpleProperty(description = "Determines the height of the list on the view.",
187  category =PropertyCategory.APPEARANCE)
188  public void Height(int height) {
189  if (height == LENGTH_PREFERRED) {
190  height = LENGTH_FILL_PARENT;
191  }
192  super.Height(height);
193  }
194 
199  @Override
200  @SimpleProperty(description = "Determines the width of the list on the view.",
201  category = PropertyCategory.APPEARANCE)
202  public void Width(int width) {
203  if (width == LENGTH_PREFERRED) {
204  width = LENGTH_FILL_PARENT;
205  }
206  super.Width(width);
207  }
208 
216  defaultValue = DEFAULT_ENABLED ? "True" : "False")
217  @SimpleProperty(description = "Sets visibility of ShowFilterBar. True will show the bar, " +
218  "False will hide it.")
219  public void ShowFilterBar(boolean showFilter) {
220  this.showFilter = showFilter;
221  if (showFilter) {
222  txtSearchBox.setVisibility(View.VISIBLE);
223  }
224  else {
225  txtSearchBox.setVisibility(View.GONE);
226  }
227  }
228 
236  description = "Returns current state of ShowFilterBar for visibility.")
237  public boolean ShowFilterBar() {
238  return showFilter;
239  }
240 
245  @SimpleProperty(description="List of text elements to show in the ListView. This will " +
246  "signal an error if the elements are not text strings.",
247  category = PropertyCategory.BEHAVIOR)
248  public void Elements(YailList itemsList) {
249  items = ElementsUtil.elements(itemsList, "Listview");
250  setAdapterData();
251  }
252 
260  public YailList Elements() {
261  return items;
262  }
263 
268  @DesignerProperty(editorType = PropertyTypeConstants.PROPERTY_TYPE_TEXTAREA, defaultValue = "")
269  @SimpleProperty(description="The TextView elements specified as a string with the " +
270  "items separated by commas " +
271  "such as: Cheese,Fruit,Bacon,Radish. Each word before the comma will be an element in the " +
272  "list.", category = PropertyCategory.BEHAVIOR)
273  public void ElementsFromString(String itemstring) {
274  items = ElementsUtil.elementsFromString(itemstring);
275  setAdapterData();
276  }
277 
281  public void setAdapterData(){
282  adapter = new ArrayAdapter<Spannable>(container.$context(), android.R.layout.simple_list_item_1,
284  view.setAdapter(adapter);
285 
286  adapterCopy = new ArrayAdapter<Spannable>(container.$context(), android.R.layout.simple_list_item_1);
287  for (int i = 0; i < adapter.getCount(); ++i) {
288  adapterCopy.insert(adapter.getItem(i), i);
289  }
290  }
291 
292  public Spannable[] itemsToColoredText() {
293  // TODO(hal): Generalize this so that different items could have different
294  // colors and even fonts and sizes
295  int size = items.size();
296  int displayTextSize = textSize;
297  Spannable [] objects = new Spannable[size];
298  for (int i = 1; i <= size; i++) {
299  // Note that the ListPicker and otherPickers pickers convert Yail lists to string by calling
300  // YailList.ToStringArray.
301  // ListView however, does the string conversion via the adapter, so we must ensure
302  // that the adapter uses YailListElementToSring
303  String itemString = YailList.YailListElementToString(items.get(i));
304  // Is there a more efficient way to do conversion to spannable strings that does not
305  // need to allocate new objects?
306  Spannable chars = new SpannableString(itemString);
307  chars.setSpan(new ForegroundColorSpan(textColor),0,chars.length(),0);
309  displayTextSize = (int) (textSize * container.$form().deviceDensity());
310  }
311  chars.setSpan(new AbsoluteSizeSpan(displayTextSize),0,chars.length(),0);
312  objects[i - 1] = chars;
313  }
314  return objects;
315  }
316 
324  description = "The index of the currently selected item, starting at " +
325  "1. If no item is selected, the value will be 0. If an attempt is " +
326  "made to set this to a number less than 1 or greater than the number " +
327  "of items in the ListView, SelectionIndex will be set to 0, and " +
328  "Selection will be set to the empty text.",
329  category = PropertyCategory.BEHAVIOR)
330  public int SelectionIndex() {
331  return selectionIndex;
332  }
333 
340  @SimpleProperty(description="Specifies the position of the selected item in the ListView. " +
341  "This could be used to retrieve" +
342  "the text at the chosen position. If an attempt is made to set this to a " +
343  "number less than 1 or greater than the number of items in the ListView, SelectionIndex " +
344  "will be set to 0, and Selection will be set to the empty text."
345  ,
346  category = PropertyCategory.BEHAVIOR)
347  public void SelectionIndex(int index){
348  selectionIndex = ElementsUtil.selectionIndex(index, items);
349  // Now, we need to change Selection to correspond to SelectionIndex.
350  selection = ElementsUtil.setSelectionFromIndex(index, items);
351 
352  updateSelectionIndex();
353  }
354 
358  @SimpleProperty(description="Returns the text last selected in the ListView.",
359  category = PropertyCategory
360  .BEHAVIOR)
361  public String Selection(){
362  return selection;
363  }
364 
371  defaultValue = "")
373  public void Selection(String value) {
374  selection = value;
375  // Now, we need to change SelectionIndex to correspond to Selection.
376  selectionIndex = ElementsUtil.setSelectedIndexFromValue(value, items);
377 
378  updateSelectionIndex();
379  }
380 
385  private void updateSelectionIndex() {
386  if (selectionIndex > 0) {
387  // Store last active view to refocus it later
388  View previousView = container.$form().getCurrentFocus();
389 
390  // We need to request focus from the ListView in order for the
391  // drawable changes to apply to the active item view.
392  view.requestFocusFromTouch();
393 
394  // Set selection to 0-based index (which will in turn call
395  // the necessary listener)
396  view.setSelection(selectionIndex - 1);
397 
398  // Re-focus last view
399  if (previousView != null) {
400  previousView.requestFocus();
401  }
402  } else if (lastSelected != null) {
403  // Un-set selected drawable from the last selected item
404  lastSelected.setBackgroundDrawable(UNSELECTED_DRAWABLE);
405  lastSelected = null;
406  }
407  }
408 
413  @Override
414  public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
415  Spannable item = (Spannable) parent.getAdapter().getItem(position);
416  this.selection = item.toString();
417  this.selectionIndex = adapterCopy.getPosition(item) + 1; // AI lists are 1-based
418 
419  // Un-set drawable from previous last selected item
420  if (lastSelected != null) {
421  lastSelected.setBackgroundDrawable(UNSELECTED_DRAWABLE);
422  }
423 
424  // Set selected drawable to current view
425  view.setBackgroundDrawable(selectionDrawable);
426 
427  // Update last selected
428  lastSelected = view;
429 
430  AfterPicking();
431  }
432 
437  @Override
438  public void onItemSelected(AdapterView<?> adapterView, View view, int i, long l) {
439  // Defer to item click
440  onItemClick(adapterView, view, i, l);
441  }
442 
443  @Override
444  public void onNothingSelected(AdapterView<?> adapterView) {
445 
446  }
447 
452  @SimpleEvent(description = "Simple event to be raised after the an element has been chosen in the" +
453  " list. The selected element is available in the Selection property.")
454  public void AfterPicking() {
455  EventDispatcher.dispatchEvent(this, "AfterPicking");
456  }
457 
463  public void setBackgroundColor(int color) {
464  backgroundColor = color;
465  view.setBackgroundColor(backgroundColor);
466  listViewLayout.setBackgroundColor(backgroundColor);
467  // Keeps background color behind list elements correct when scrolling through listView
468  view.setCacheColorHint(backgroundColor);
469  }
470 
480  description = "The color of the listview background.",
481  category = PropertyCategory.APPEARANCE)
482  @IsColor
483  public int BackgroundColor() {
484  return backgroundColor;
485  }
486 
499  defaultValue = Component.DEFAULT_VALUE_COLOR_BLACK)
501  public void BackgroundColor(int argb) {
502  backgroundColor = argb;
503  setBackgroundColor(backgroundColor);
504  }
505 
515  @SimpleProperty(description = "The color of the item when it is selected.")
516  @IsColor
517  public int SelectionColor() {
518  return selectionColor;
519  }
520 
534  defaultValue = Component.DEFAULT_VALUE_COLOR_LTGRAY)
536  public void SelectionColor(int argb) {
537  selectionColor = argb;
538  this.selectionDrawable = new GradientDrawable(
539  GradientDrawable.Orientation.TOP_BOTTOM, new int[]{argb, argb});
540  }
541 
551  description = "The text color of the listview items.",
552  category = PropertyCategory.APPEARANCE)
553  @IsColor
554  public int TextColor() {
555  return textColor;
556  }
557 
570  defaultValue = Component.DEFAULT_VALUE_COLOR_WHITE)
572  public void TextColor(int argb) {
573  textColor = argb;
574  setAdapterData();
575  }
576 
583  description = "The text size of the listview items.",
584  category = PropertyCategory.APPEARANCE)
585  public int TextSize() {
586  return textSize;
587  }
588 
595  defaultValue = DEFAULT_TEXT_SIZE + "")
597  public void TextSize(int fontSize) {
598  if(fontSize>1000)
599  textSize = 999;
600  else
601  textSize = fontSize;
602  setAdapterData();
603  }
604 }
com.google.appinventor.components.runtime.EventDispatcher
Definition: EventDispatcher.java:22
com.google.appinventor.components.runtime.util.YailList
Definition: YailList.java:26
com.google.appinventor.components.runtime.util.YailList.YailListElementToString
static String YailListElementToString(Object element)
Definition: YailList.java:131
com.google.appinventor.components.runtime.ListView.ListView
ListView(ComponentContainer container)
Definition: ListView.java:105
com.google.appinventor.components.runtime.ListView.SelectionColor
void SelectionColor(int argb)
Definition: ListView.java:536
com.google.appinventor.components.runtime.ListView.Selection
String Selection()
Definition: ListView.java:361
com.google.appinventor.components.runtime.util
-*- mode: java; c-basic-offset: 2; -*-
Definition: AccountChooser.java:7
com.google.appinventor.components.common.YaVersion
Definition: YaVersion.java:14
com.google.appinventor.components.runtime.ListView.ElementsFromString
void ElementsFromString(String itemstring)
Definition: ListView.java:273
com.google.appinventor.components.annotations.DesignerProperty
Definition: DesignerProperty.java:25
com.google.appinventor.components.runtime.AndroidViewComponent.Height
int Height()
Definition: AndroidViewComponent.java:178
com.google.appinventor.components.common.PropertyTypeConstants.PROPERTY_TYPE_STRING
static final String PROPERTY_TYPE_STRING
Definition: PropertyTypeConstants.java:237
com.google.appinventor.components
com.google.appinventor.components.common.PropertyTypeConstants.PROPERTY_TYPE_NON_NEGATIVE_INTEGER
static final String PROPERTY_TYPE_NON_NEGATIVE_INTEGER
Definition: PropertyTypeConstants.java:206
com.google.appinventor.components.runtime.Component.DEFAULT_VALUE_COLOR_WHITE
static final String DEFAULT_VALUE_COLOR_WHITE
Definition: Component.java:82
com.google.appinventor.components.runtime.ListView.Elements
YailList Elements()
Definition: ListView.java:260
com.google.appinventor.components.runtime.util.ElementsUtil.selectionIndex
static int selectionIndex(int index, YailList items)
Definition: ElementsUtil.java:45
com.google.appinventor.components.runtime.ListView.setBackgroundColor
void setBackgroundColor(int color)
Definition: ListView.java:463
com.google.appinventor.components.runtime.ListView.TextColor
int TextColor()
Definition: ListView.java:554
com.google.appinventor.components.runtime.Component.LENGTH_FILL_PARENT
static final int LENGTH_FILL_PARENT
Definition: Component.java:119
com.google.appinventor.components.common.PropertyTypeConstants.PROPERTY_TYPE_BOOLEAN
static final String PROPERTY_TYPE_BOOLEAN
Definition: PropertyTypeConstants.java:35
com.google.appinventor.components.runtime.Component.COLOR_LTGRAY
static final int COLOR_LTGRAY
Definition: Component.java:61
com.google.appinventor.components.annotations.DesignerComponent
Definition: DesignerComponent.java:22
com.google.appinventor.components.annotations.SimpleEvent
Definition: SimpleEvent.java:20
com.google.appinventor.components.annotations.PropertyCategory.BEHAVIOR
BEHAVIOR
Definition: PropertyCategory.java:15
com.google.appinventor.components.runtime.AndroidViewComponent.Width
int Width()
Definition: AndroidViewComponent.java:86
com.google.appinventor.components.runtime.ListView.SelectionColor
int SelectionColor()
Definition: ListView.java:517
com.google.appinventor.components.runtime.ListView.ShowFilterBar
boolean ShowFilterBar()
Definition: ListView.java:237
com.google.appinventor.components.runtime.ListView.SelectionIndex
int SelectionIndex()
Definition: ListView.java:330
com.google.appinventor.components.runtime.ListView.Selection
void Selection(String value)
Definition: ListView.java:373
com.google.appinventor.components.runtime.ComponentContainer.$add
void $add(AndroidViewComponent component)
com.google.appinventor.components.runtime.ListView.getView
View getView()
Definition: ListView.java:177
com.google.appinventor.components.runtime.ListView.setAdapterData
void setAdapterData()
Definition: ListView.java:281
com.google.appinventor.components.runtime.util.ElementsUtil.setSelectedIndexFromValue
static int setSelectedIndexFromValue(String value, YailList items)
Definition: ElementsUtil.java:60
com.google.appinventor.components.common.PropertyTypeConstants.PROPERTY_TYPE_TEXTAREA
static final String PROPERTY_TYPE_TEXTAREA
Definition: PropertyTypeConstants.java:248
com.google.appinventor.components.runtime.util.ElementsUtil.elements
static YailList elements(YailList itemList, String componentName)
Definition: ElementsUtil.java:33
com.google.appinventor.components.runtime.ListView.TextColor
void TextColor(int argb)
Definition: ListView.java:572
com.google.appinventor.components.runtime.EventDispatcher.dispatchEvent
static boolean dispatchEvent(Component component, String eventName, Object...args)
Definition: EventDispatcher.java:188
com.google.appinventor.components.runtime.ListView.onItemSelected
void onItemSelected(AdapterView<?> adapterView, View view, int i, long l)
Definition: ListView.java:438
com.google.appinventor.components.runtime.ListView.container
final ComponentContainer container
Definition: ListView.java:71
com.google.appinventor.components.runtime.ListView.TextSize
int TextSize()
Definition: ListView.java:585
com.google.appinventor.components.annotations.SimpleProperty
Definition: SimpleProperty.java:23
com.google.appinventor.components.runtime.Component.LENGTH_PREFERRED
static final int LENGTH_PREFERRED
Definition: Component.java:118
com.google.appinventor.components.runtime.util.ElementsUtil.elementsFromString
static YailList elementsFromString(String itemString)
Definition: ElementsUtil.java:17
com.google.appinventor.components.runtime.ListView.AfterPicking
void AfterPicking()
Definition: ListView.java:454
com.google.appinventor.components.runtime.ListView.itemsToColoredText
Spannable[] itemsToColoredText()
Definition: ListView.java:292
com.google.appinventor.components.runtime.ListView.BackgroundColor
int BackgroundColor()
Definition: ListView.java:483
com.google.appinventor.components.annotations.PropertyCategory
Definition: PropertyCategory.java:13
com.google.appinventor.components.runtime.ListView.BackgroundColor
void BackgroundColor(int argb)
Definition: ListView.java:501
com.google.appinventor.components.runtime.Component.COLOR_BLACK
static final int COLOR_BLACK
Definition: Component.java:55
com.google.appinventor.components.runtime.ComponentContainer
Definition: ComponentContainer.java:16
com.google.appinventor.components.runtime
Copyright 2009-2011 Google, All Rights reserved.
Definition: AccelerometerSensor.java:8
com.google.appinventor.components.runtime.Component
Definition: Component.java:17
com.google.appinventor.components.runtime.ListView
Definition: ListView.java:64
com.google.appinventor.components.runtime.util.ElementsUtil.setSelectionFromIndex
static String setSelectionFromIndex(int index, YailList items)
Definition: ElementsUtil.java:53
com.google.appinventor.components.common
Definition: ComponentCategory.java:7
com.google.appinventor.components.common.ComponentCategory
Definition: ComponentCategory.java:48
com.google.appinventor.components.annotations.SimpleObject
Definition: SimpleObject.java:23
com.google.appinventor.components.common.PropertyTypeConstants.PROPERTY_TYPE_COLOR
static final String PROPERTY_TYPE_COLOR
Definition: PropertyTypeConstants.java:63
com.google.appinventor.components.runtime.AppInventorCompatActivity
Definition: AppInventorCompatActivity.java:40
com.google.appinventor.components.runtime.Component.COLOR_WHITE
static final int COLOR_WHITE
Definition: Component.java:66
com.google
com
com.google.appinventor.components.runtime.AppInventorCompatActivity.isClassicMode
static boolean isClassicMode()
Definition: AppInventorCompatActivity.java:237
com.google.appinventor.components.runtime.Component.DEFAULT_VALUE_COLOR_LTGRAY
static final String DEFAULT_VALUE_COLOR_LTGRAY
Definition: Component.java:77
com.google.appinventor.components.runtime.Form.getCompatibilityMode
static boolean getCompatibilityMode()
Definition: Form.java:2554
com.google.appinventor.components.runtime.ComponentContainer.$form
Form $form()
com.google.appinventor.components.runtime.ComponentContainer.$context
Activity $context()
com.google.appinventor.components.runtime.util.YailList.makeEmptyList
static YailList makeEmptyList()
Definition: YailList.java:52
com.google.appinventor.components.runtime.ListView.onNothingSelected
void onNothingSelected(AdapterView<?> adapterView)
Definition: ListView.java:444
com.google.appinventor.components.runtime.ListView.onItemClick
void onItemClick(AdapterView<?> parent, View view, int position, long id)
Definition: ListView.java:414
com.google.appinventor.components.runtime.LinearLayout
Definition: LinearLayout.java:20
com.google.appinventor.components.runtime.AndroidViewComponent
Definition: AndroidViewComponent.java:27
com.google.appinventor.components.runtime.ListView.TextSize
void TextSize(int fontSize)
Definition: ListView.java:597
com.google.appinventor.components.annotations.IsColor
Definition: IsColor.java:13
com.google.appinventor.components.annotations.PropertyCategory.APPEARANCE
APPEARANCE
Definition: PropertyCategory.java:16
com.google.appinventor.components.common.PropertyTypeConstants
Definition: PropertyTypeConstants.java:14
com.google.appinventor.components.annotations
com.google.appinventor.components.runtime.Component.DEFAULT_VALUE_COLOR_BLACK
static final String DEFAULT_VALUE_COLOR_BLACK
Definition: Component.java:71
com.google.appinventor.components.runtime.util.ElementsUtil
Definition: ElementsUtil.java:15
com.google.appinventor.components.runtime.util.YailList.size
int size()
Definition: YailList.java:172
com.google.appinventor