I have such a problem - I want to make spinner\'s scrollbar always visible. But for spinner function
setScrollbarFadingEnabled(false);
caus
After a initial investigation, I'm thinking that is not possible to call setScrollbarFadingEnabled(false);
in a Spinner.
I have read the implementation of the Class Spinner.java
and View.java
(this last one implements the setScrollbarFadingEnabled(boolean)
of the API16 and the problem is the line:
cache.scrollBar.setAlpha(255);
Probably cache.scrollBar
is null at this point and i didnt find any way to force some initialization of this attribute.
The most methods who manage this attribute are protected or private, so we can't just call them.
I'll continue to research this problem in order to find a possible solution, but for now, and considering that nobody have answered this question yet, i'm thinking that is not possible.
As it's not easy to access the underlying ListView
of the spinner, I found a simple solution for this.
Create a style in styles.xml, And set scrollbarFadeDuration
to some endless value.
<style name="AlwaysEnableScrollBar" parent="Widget.AppCompat.ListView.DropDown">
<item name="android:scrollbarFadeDuration">10000000</item>
</style>
Then set that in the spinner theme:
<Spinner
...
android:theme="@style/AlwaysEnableScrollBar"/>
Thank @nandeesh for his/her answer and also @Eng.Fouad for his/her answer on another page.
public class VisibleScrollbarSpinner extends Spinner {
@Override public boolean performClick() {
final boolean superResult = super.performClick();
try {
final Field mPopupField = Spinner.class.getDeclaredField("mPopup");
mPopupField.setAccessible(true);
//noinspection ConstantConditions
((ListPopupWindow) mPopupField.get(this)).getListView().setScrollbarFadingEnabled(false);
mPopupField.setAccessible(false);
} catch (NoSuchFieldException | IllegalAccessException e) {
Log.e(TAG, e.toString(), e);
}
return superResult;
}
public VisibleScrollbarSpinner(Context context) { super(context); }
public VisibleScrollbarSpinner(Context context, int mode) { super(context, mode); }
public VisibleScrollbarSpinner(Context context, AttributeSet attrs) { super(context, attrs); }
public VisibleScrollbarSpinner(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); }
public VisibleScrollbarSpinner(Context context, AttributeSet attrs, int defStyleAttr, int mode) { super(context, attrs, defStyleAttr, mode); }
}
Spinner does not have a scrollbar, Hence you are getting NullPointerException.
The popup shown by spinner has a scrollbar. So you need to change the properties of the ListView shown by spinner. But ListView itself is not exposed by Spinner by any public methods.
Even if you get the ListPopupWindow by reflection, a further problem arises, that ListPopupWindow's ListView is only created after you click the Spinner.
But OnClickListener of the Spinner cannot be registered , to set the ListView Properties after the show.
You could create a Custom Spinner with performClick overridden and then get mPopup by reflection. and use mPopup.getListView().setScrollbarFadingEnabled(false)
But If you are going to create a custom Spinner, i believe it is easier to implement the whole popup to suit your needs than using reflection.
I have noticed "setScrollbarFadingEnabled" java method and "fadeScrollbar" xml method both doesn't make any affect on spinner because the list view of spinner is wrapped up in a dialog (popup), so these properties doesn't reach the listview.
But what Actually reaches the spinner listview is THEME.
So just create a custom theme like this:
<style name="App_SpinnerStyle" >
<item name="android:fadeScrollbars">false</item>
</style>
And add it to spinner like this:
android:popupTheme="@style/App_SpinnerStyle"
Tried and tested!
in your app theme or activity them :
<item name="android:dropDownListViewStyle">@style/SpinnerStyle1</item>
declare SpinnerStyle1:
<style name="SpinnerStyle1" parent="Widget.AppCompat.ListView.DropDown">
<item name="android:divider">@color/blackText</item>
<item name="android:dividerHeight">1px</item>
<item name="android:scrollbarAlwaysDrawVerticalTrack">true</item>
</style>