Spinner 下拉项目彩色背景上的波纹效果 (appcompat-v7 V21)

Posted

技术标签:

【中文标题】Spinner 下拉项目彩色背景上的波纹效果 (appcompat-v7 V21)【英文标题】:Ripple effect on Spinner dropdown items colored background (appcompat-v7 V21) 【发布时间】:2015-03-07 18:56:04 【问题描述】:

我尝试对 Spinner 下拉项应用波纹效果,如下所示:

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_
   android:layout_
   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>

但在下拉列表中,它仅适用于第一项并且仅当当前选定的项与第一项不同时。在所有其他情况下,它用波纹颜色填充背景项目(因为没有波纹效果)。 我的代码哪里错了?

已经尝试过:在下拉项布局的背景上设置固定颜色并在 Spinner 元素下移动波纹效果不起作用,如下所示:

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_
   android:layout_
   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_
   android:layout_
   android:drawSelectorOnTop="true"
   android:dropDownSelector="@drawable/spinner_ripple" />

【问题讨论】:

【参考方案1】:

您的第二种方法是正确的,但正如this question 中所述,android:dropDownSelector 属性不起作用,这是一个众所周知的错误。

另外,如果你想改变下拉菜单的背景颜色,你需要设置Spinner'sandroid:popupBackground,而不是设置下拉项的背景。

整个解决方案是这样的:

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_
    android:layout_
    android:dropDownSelector="@drawable/spinner_ripple"
    android:popupBackground="@drawable/popup_background"
    />
...

spinner_ripple.xml(原始)

<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>

【讨论】:

以这种方式,白色背景上的波纹效果在主题级别上移动:它有效,但适用于我的应用程序中的所有微调器。因此,我不能让一个微调器对他自己的背景颜色产生与主题不同的涟漪效果。 这很不幸,但由于 Android 错误,这是唯一的方法,除非您想子类化微调器类并尝试在其中实现解决方法。 顺便说一句,你为什么想要一个与众不同的微调器? 这是由于样式选择。似乎没有其他方法,因此您的方法是正确的。非常感谢您帮助我。【参考方案2】:

如果你想让你的下拉列表项默认为白色并仅在用户触摸它们时以涟漪效果突出显示它们,你需要在 spinner_ripple.xml 可绘制对象中实现适当的状态列表:

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

这里,android:state_pressed="true" 表示只有当用户实际按下视图时才会应用选择器项。如果您想支持其他选择器状态,请查看 StateListDrawable 参考。

记住AppCompat-v7 v21不支持涟漪效应,据官方Android Developers blog:

为什么在之前的 Lollipop 上没有涟漪? 让 RippleDrawable 能够流畅运行的很多原因是 Android 5.0 的新 RenderThread。为了优化旧版 Android 的性能,我们暂时不使用 RippleDrawable。

所以它只适用于 Lollypop。

【讨论】:

这样,当项目被按下时,背景白色不会持续存在,它会更改为下拉列表的主题背景颜色。 对,看看我的另一个答案。这解决了所有问题。 state_pressed="false" 属性在第二项中似乎是多余的。【参考方案3】:

我相信您的spinner_ripple.xml 中需要两层

<!-- Background -->
<ripple android:color="#ff00ff00">
    <item android:drawable="@android:color/black" />
<ripple />

<!-- Ripple color -->
<ripple android:color="#ff00ff00">
    <item android:drawable="@android:color/white" />
<ripple />

【讨论】:

selector下xml同级的两个ripple元素?我会尝试,但我认为这不是正确的方法。谢谢。

以上是关于Spinner 下拉项目彩色背景上的波纹效果 (appcompat-v7 V21)的主要内容,如果未能解决你的问题,请参考以下文章

Android Studio Spinner自定义背景及右边下拉的图标

imageview 上的波纹效果

选定状态覆盖的 Android 波纹效果

如何制作Spinner的Hint提示效果,并自定义Spinner样式

Android Spinner下拉框使用

android: Android水波纹点击效果