Unverified Commit f936ee78 authored by Evaldas Latoškinas's avatar Evaldas Latoškinas Committed by GitHub

Allow ListView item highlighting programatically (#2094)

* Refactor & implement highlighting of selected item (both via blocks and listeners)
* Fix NPE with regards to last seen view in ListView selection
parent e1ab8187
......@@ -7,7 +7,10 @@
package com.google.appinventor.components.runtime;
import android.graphics.Color;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.GradientDrawable;
import android.graphics.drawable.StateListDrawable;
import android.text.Editable;
import android.text.Spannable;
import android.text.SpannableString;
......@@ -16,6 +19,7 @@ import android.text.style.AbsoluteSizeSpan;
import android.text.style.ForegroundColorSpan;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AbsListView;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.EditText;
......@@ -57,7 +61,8 @@ import com.google.appinventor.components.runtime.util.YailList;
nonVisible = false,
iconName = "images/listView.png")
@SimpleObject
public final class ListView extends AndroidViewComponent implements AdapterView.OnItemClickListener {
public final class ListView extends AndroidViewComponent implements AdapterView.OnItemClickListener,
AdapterView.OnItemSelectedListener {
private static final String LOG_TAG = "ListView";
......@@ -85,6 +90,10 @@ public final class ListView extends AndroidViewComponent implements AdapterView.
private int selectionColor;
private static final int DEFAULT_SELECTION_COLOR = Component.COLOR_LTGRAY;
private static final Drawable UNSELECTED_DRAWABLE = new ColorDrawable(Color.TRANSPARENT);
private Drawable selectionDrawable;
private View lastSelected;
private int textSize;
private static final int DEFAULT_TEXT_SIZE = 22;
......@@ -101,8 +110,10 @@ public final class ListView extends AndroidViewComponent implements AdapterView.
SelectionIndex(0);
view = new android.widget.ListView(container.$context());
view.setOnItemClickListener(this);
view.setOnItemSelectedListener(this);
view.setChoiceMode(android.widget.ListView.CHOICE_MODE_SINGLE);
view.setScrollingCacheEnabled(false);
view.setSelector(new StateListDrawable()); // Set to empty selector to prevent issues with dynamic highlighting
listViewLayout = new LinearLayout(container.$context());
listViewLayout.setOrientation(LinearLayout.VERTICAL);
......@@ -337,6 +348,8 @@ public final class ListView extends AndroidViewComponent implements AdapterView.
selectionIndex = ElementsUtil.selectionIndex(index, items);
// Now, we need to change Selection to correspond to SelectionIndex.
selection = ElementsUtil.setSelectionFromIndex(index, items);
updateSelectionIndex();
}
/**
......@@ -361,6 +374,36 @@ public final class ListView extends AndroidViewComponent implements AdapterView.
selection = value;
// Now, we need to change SelectionIndex to correspond to Selection.
selectionIndex = ElementsUtil.setSelectedIndexFromValue(value, items);
updateSelectionIndex();
}
/**
* Action to take after updating selection index.
* Handles highlighting the newly updated item.
*/
private void updateSelectionIndex() {
if (selectionIndex > 0) {
// Store last active view to refocus it later
View previousView = Form.getActiveForm().getCurrentFocus();
// We need to request focus from the ListView in order for the
// drawable changes to apply to the active item view.
view.requestFocusFromTouch();
// Set selection to 0-based index (which will in turn call
// the necessary listener)
view.setSelection(selectionIndex - 1);
// Re-focus last view
if (previousView != null) {
previousView.requestFocus();
}
} else if (lastSelected != null) {
// Un-set selected drawable from the last selected item
lastSelected.setBackgroundDrawable(UNSELECTED_DRAWABLE);
lastSelected = null;
}
}
/**
......@@ -373,9 +416,35 @@ public final class ListView extends AndroidViewComponent implements AdapterView.
this.selection = item.toString();
this.selectionIndex = adapterCopy.getPosition(item) + 1; // AI lists are 1-based
// Un-set drawable from previous last selected item
if (lastSelected != null) {
lastSelected.setBackgroundDrawable(UNSELECTED_DRAWABLE);
}
// Set selected drawable to current view
view.setBackgroundDrawable(selectionDrawable);
// Update last selected
lastSelected = view;
AfterPicking();
}
/**
* Simple event to raise when the component is selected. Implementation of
* AdapterView.OnItemSelectedListener.
*/
@Override
public void onItemSelected(AdapterView<?> adapterView, View view, int i, long l) {
// Defer to item click
onItemClick(adapterView, view, i, l);
}
@Override
public void onNothingSelected(AdapterView<?> adapterView) {
}
/**
* Simple event to be raised after the an element has been chosen in the list.
* The selected element is available in the {@link #Selection(String)} property.
......@@ -466,9 +535,8 @@ public final class ListView extends AndroidViewComponent implements AdapterView.
@SimpleProperty
public void SelectionColor(int argb) {
selectionColor = argb;
view.setSelector(new GradientDrawable(
GradientDrawable.Orientation.TOP_BOTTOM, new int[]{argb, argb}
));
this.selectionDrawable = new GradientDrawable(
GradientDrawable.Orientation.TOP_BOTTOM, new int[]{argb, argb});
}
/**
......@@ -533,5 +601,4 @@ public final class ListView extends AndroidViewComponent implements AdapterView.
textSize = fontSize;
setAdapterData();
}
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment