Search code examples
androidandroid-spinnerandroid-appcompatmaterial-designrippledrawable

Ripple effect on Spinner dropdown items colored background (appcompat-v7 V21)


I tried to apply ripple effect on Spinner dropdown items, like this:

activity.java

    ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource(
            this, R.array.array_name, R.layout.simple_spinner_dropdown_item);
    adapter.setDropDownViewResource(R.layout.simple_spinner_dropdown_item);
    Spinner mSpinner = (Spinner) findViewById(R.id.spinner);
    mSpinner.setAdapter(adapter);

simple_spinner_dropdown_item.xml

<?xml version="1.0" encoding="utf-8"?>
<CheckedTextView xmlns:android="http://schemas.android.com/apk/res/android"
   android:id="@android:id/text1"
   android:layout_width="match_parent"
   android:layout_height="wrap_content"
   android:background="@drawable/spinner_ripple"
   android:ellipsize="marquee"
   android:gravity="center_horizontal"
   android:padding="10dip"
   android:singleLine="true"
   android:textSize="14sp" />

spinner_ripple.xml

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item>
   <ripple android:color="?android:attr/colorControlHighlight">
       <item><shape>
                  <solid android:color="@android:color/white" />
              </shape>
       </item>
   </ripple>
</item>
</selector>

but in the dropdown list it works only for the first item and only if the current selected item is another one than the first. In all other cases it fills background item with ripple color (as no ripple effect). Where is wrong my code?

Already tried: doesnt work to set fixed color on background of dropdown item layout and move ripple effect under Spinner element, like this:

simple_spinner_dropdown_item.xml

<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
   android:id="@android:id/text1"
   android:layout_width="match_parent"
   android:layout_height="wrap_content"
   android:background="@android:color/white"
   android:ellipsize="marquee"
   android:gravity="center_horizontal"
   android:padding="10dip"
   android:singleLine="true"
   android:textSize="14sp" />

activity_layout.xml

<Spinner
   android:id="@+id/spinner"
   android:layout_width="wrap_content"
   android:layout_height="wrap_content"
   android:drawSelectorOnTop="true"
   android:dropDownSelector="@drawable/spinner_ripple" />

Solution

  • Your second approach is correct, but as mentioned in this question, android:dropDownSelector attribute does not work and it's a well known bug.

    Also, if you want to change drop-down background color, you need to set Spinner's android:popupBackground, instead of setting the background of the drop-down item.

    The whole solution will be like this:

    popup_background.xml

    <!--Based on Android's popup_background_material.xml-->
    <!--This changes the background of the drop-down-->
    <shape xmlns:android="http://schemas.android.com/apk/res/android"
            android:shape="rectangle">
        <corners android:radius="2dp" />
        <solid android:color="@android:color/white" />
    </shape>
    

    styles.xml

    <resources>
        <style name="AppTheme" parent="android:Theme.Material.Light">
            <!--Workaround for the Android bug-->
            <item name="android:dropDownListViewStyle">@style/Theme.MyListView</item>
        </style>
    
        <style name="Theme.MyListView" parent="@android:style/Widget.Material.ListView.DropDown">
            <item name="android:listSelector">@drawable/spinner_ripple</item>
        </style>
    </resources>
    

    activity.xml

    ...
    <Spinner
        android:id="@+id/spinner"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:dropDownSelector="@drawable/spinner_ripple"
        android:popupBackground="@drawable/popup_background"
        />
    ...
    

    spinner_ripple.xml (original)

    <selector xmlns:android="http://schemas.android.com/apk/res/android">
        <item>
            <ripple android:color="?android:attr/colorControlHighlight">
                <item>
                    <shape>
                        <solid android:color="@android:color/white" />
                    </shape>
                </item>
            </ripple>
        </item>
    </selector>