Android 6.0.1 上的微调器内部填充更大

Spinner inner padding is larger on Android 6.0.1

简介:

在 Android 6.0.1 的新版本中,似乎 Android 对 Spinner 组件进行了一些更改,因为默认情况下,向下胡萝卜周围的内部填充有点大。

我在一个应用程序上注意到了这一点,我没有修改代码中的任何内容,只是更新了设备上的 OS,但微调器的尺寸不同。

情况:

我在 RelativeLayout 中有 2 个并排的微调器(请注意其余组件,我添加了所有内容以便您可以看到布局的这一部分 - 删除了完全不必要的属性或视图 ID )

<RelativeLayout
    android:id="@+id/header"
    android:layout_width="match_parent"
    android:layout_height="wrap_content">

    <LinearLayout
        android:id="@+id/container_for_buttons_on_the_right"
        android:layout_width="wrap_content"
        android:layout_height="48dp"
        android:layout_alignParentEnd="true"
        android:layout_alignParentRight="true">

        <!-- Buttons here-->
    </LinearLayout>

    <android.support.v7.widget.AppCompatSpinner
        android:id="@+id/spinner_1"
        android:layout_width="wrap_content"
        android:layout_height="48dp"
        android:layout_alignParentLeft="true"
        android:layout_alignParentStart="true" />

    <ViewSwitcher
        android:id="@+id/spinner_switch"
        android:layout_width="wrap_content"
        android:layout_height="48dp"
        android:layout_toEndOf="@id/spinner_1"
        android:layout_toLeftOf="@id/container_for_buttons_on_the_right"
        android:layout_toRightOf="@id/spinner_1"
        android:layout_toStartOf="@id/container_for_buttons_on_the_right"
        android:inAnimation="@anim/fade_in"
        android:outAnimation="@anim/fade_out">

        <android.support.v7.widget.AppCompatSpinner
            android:layout_width="wrap_content"
            android:layout_height="match_parent" />

        <ImageView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content" />
        <!-- ImageView properties are incomplete but I need it there.-->
    </ViewSwitcher>
</RelativeLayout>

getView() 方法的 Spinner 适配器使用的布局是这样的:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="48dp"
    android:orientation="horizontal"
    android:paddingLeft="8dp"
    android:paddingRight="8dp">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:layout_weight="1"
        android:ellipsize="end"
        android:gravity="center_vertical"
        android:singleLine="true"
        tools:text="Test" />

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:layout_weight="0"
        android:gravity="center"
        android:paddingLeft="4dp"
        android:singleLine="true"
        android:textColor="@color/text_primary"
        android:textSize="@dimen/text_size_body"
        tools:ignore="RtlHardcoded,RtlSymmetry"
        tools:text="7%" />
</LinearLayout>

举例:

该屏幕截图由 2 个单独的屏幕截图合并而成:

  1. 最上面的那个是用 Nexus 5 设备 运行 在 Android 6.0[ 上拍摄的=55=]
  2. 下面的也是在 Nexus 5 设备上拍摄的,但是 运行 在 Android 6.0.1[=50= 上]

  • 编辑 1

使用支持库中的 AppCompatSpinner 不会改变行为。使用的支持库版本是 23.1.1

通过为微调器构建自定义背景,我以最小的努力解决了这个问题。

使用 AppCompatSpinner 我必须为背景创建 2 个 xml,我们称之为 spinner_background.xml

1. 第一个进入 drawable 文件夹,看起来像这样,spinner_background.xml:

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android"
    android:opacity="transparent">
    <item
        android:width="24dp"
        android:height="24dp"
        android:drawable="@drawable/selector_background_borderless"
        android:gravity="end|center_vertical" />
    <item android:drawable="@drawable/bg_spinner_anchor" />
</layer-list>

其中 selector_background_borderless 是一个普通的选择器(我添加了您需要的最少项目,您可以探索它是 v21+ 的 ripple 替代品。事实上我建议您这样做):

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:drawable="#19000000" android:state_pressed="true" />
    <item android:drawable="@android:color/transparent" />
</selector>

bg_spinner_anchor 是插入符号的 9patch PNG。我使用了这些资产:bg_spinner_anchor

2. 第二个进入 drawable-v23 文件夹以正确支持波纹,看起来像这样,spinner_background.xml:

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android"
    android:paddingEnd="16dp"
    android:paddingLeft="0dp"
    android:paddingMode="stack"
    android:paddingRight="0dp"
    android:paddingStart="0dp">
    <item
        android:width="24dp"
        android:height="24dp"
        android:drawable="@drawable/selector_background_borderless"
        android:gravity="end|center_vertical" />

    <item
        android:width="24dp"
        android:height="24dp"
        android:drawable="@drawable/ic_spinner_caret"
        android:gravity="end|center_vertical" />
</layer-list>

其中 ic_spinner_caret 是从 Android 源代码中使用的向量,如下所示。您还应该将其添加到您的 drawable-v23 文件夹中:

<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
    android:width="24dp"
    android:height="24dp"
    android:viewportWidth="24.0"
    android:viewportHeight="24.0"
    android:tint="?attr/colorControlNormal">
    <path
        android:pathData="M7,10l5,5,5-5z"
        android:fillColor="#524e4a"/>
</vector>

学分来自 Android UI 指南工具包中的 alanv

我遇到了同样的问题,我的计划是 回滚 仅针对 v23 的 6.0.1 更新。

  1. 确保您的 Spinner 有附加的样式。例如在下面的示例中命名为 Widget.Spinner 的样式:
<Spinner
    android:id="@+id/spinner_1"
    style="@style/Widget.Spinner"
    android:layout_width="64dp"
    android:layout_height="64dp"/>
  1. values-v23 目录下创建(如果不存在)styles.xml(更改将仅应用于 API v23)。例如,参见下面的 Widget.Spinner 样式定义示例:
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <style name="Widget.Spinner" parent="Widget.AppCompat.Spinner">
        <item name="android:background">@drawable/spinner_background_material</item>
    </style>
</resources>

该样式的父项是 Widget.AppCompat.Spinner,它用我们将从 6.0.1 源回滚 的那个重新定义它的 android:background

请注意,如果您还针对其他版本,则需要在 values 目录下添加默认 styles.xml 条目

<style name="Widget.Spinner" parent="Widget.AppCompat.Spinner"/>

因为定义另一个通用样式比定义不同的布局 xml 文件更容易,而且您的项目无论如何都应该在 values 目录下有一个通用 styles.xml,对吗? :)

  1. https://android.googlesource.com/platform/frameworks/base.git/+/android-6.0.1_r3/core/res/res/drawable/ 引入 spinner_background_material.xml。再次将其保存在 drawable-v23 下,我们将确保仅更改 API v23。

文件的默认内容是:

<layer-list xmlns:android="http://schemas.android.com/apk/res/android"
    android:paddingMode="stack"
    android:paddingStart="0dp"
    android:paddingEnd="48dp"
    android:paddingLeft="0dp"
    android:paddingRight="0dp">

    <item
        android:gravity="end|fill_vertical"
        android:width="48dp"
        android:drawable="@drawable/control_background_40dp_material" />

    <item
        android:drawable="@drawable/ic_spinner_caret"
        android:gravity="end|center_vertical"
        android:width="24dp"
        android:height="24dp"
        android:end="12dp" />
</layer-list>

现在,这是您可能想要调整的文件。我更改了此文件以调整插入符位置:
a) 设置 layer-listandroid:paddingEnd 等于 0dp
b) 将第一项的 android:width 减半为 24dp
c) 删除了第二个项目的 android:end 属性

这些更改通过剥离背景使背景变薄,但该方法保留了涟漪效应。如果需要,请随意使用您自己的自定义值。

  1. 上面的更改不会编译,因为需要引入更多文件,因为它们将被上面的文件引用。

下载到drawable-v23(见上文link):
一)control_background_40dp_material.xml
b) ic_spinner_caret.xml

下载到color-v23:
a) 来自 https://android.googlesource.com/platform/frameworks/base.git/+/android-6.0.1_r3/core/res/res/color/control_highlight_material.xml(该文件也可能位于 drawable-v23 下,但现在让我们遵循原始源位置的模式)。请注意,该文件的 @dimen/highlight_alpha_material_colored 是从 appcompat-v7 中提取的,如果您使用一个 :) 如果没有,您可以从中引用它的值:

<item format="float" name="highlight_alpha_material_colored" type="dimen">0.26</item>

这个解决方案不是最好的,因为您需要带回您原本不拥有的文件。此外,您可能希望监视 v23 的可能更新以了解未来的任何更改。但至少更改仅包含在 v23 中。