Intro:
With the new release of Android 6.0.1, seems like Android made some changes on the Spinner component because by default, the inner padding around the down carrot is a bit bigger.
I noticed this on an app where I haven't modified anything in the code, but simply updated the OS on the device and yet the spinners have different sizes.
Situation:
I have 2 spinners one next to the other in a RelativeLayout
(mind the rest of the components, I added everything so you can see this part of the layout - removed the totally unnecessary properties or view ids)
<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>
The layout used by the Spinner adapter for the getView()
method is this:
<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>
Exemplified:
The screenshot is combined of 2 separate screenshots taken:
- The one on the top is taken on a Nexus 5 device running on Android 6.0
- The one below is also taken on a Nexus 5 device BUT running on Android 6.0.1
- EDIT 1
Using AppCompatSpinner from the support library does not change the behaviour. Support library version used is 23.1.1
I had the same issue and my plan was to rollback the 6.0.1 update for v23 only.
Spinner
has a style attached to it. For example style named asWidget.Spinner
in example below:styles.xml
undervalues-v23
directory (for changes will be applied to API v23 only). For example, seeWidget.Spinner
style definition example below:The style's parent is
Widget.AppCompat.Spinner
and it redefines it'sandroid:background
with the one we will be rolling back from 6.0.1 source.Note, that if you're targeting other versions too, you will need to add a default
styles.xml
undervalues
directory with entryfor it is easier to define another generic style rather than different layout xml files and your project should have a generic
styles.xml
undervalues
directory anyway, right? :)spinner_background_material.xml
from https://android.googlesource.com/platform/frameworks/base.git/+/android-6.0.1_r3/core/res/res/drawable/. Save it underdrawable-v23
for again, we will just make sure we're changing API v23 only.File's default content is:
Now, this is the file you might want to tweak. I made changes to this file for tweaking the caret position:
a) set
layer-list
'sandroid:paddingEnd
equal to0dp
b) halved first item's
android:width
to24dp
c) removed the second item's
android:end
attributeThe changes made background thinner, by stripping it's sides but the approach retained the ripple effects. Feel free to play around with your own custom values, if needed.
Download into
drawable-v23
(see link above):a)
control_background_40dp_material.xml
b)
ic_spinner_caret.xml
Download into
color-v23
:a)
control_highlight_material.xml
from https://android.googlesource.com/platform/frameworks/base.git/+/android-6.0.1_r3/core/res/res/color/ (this file can probably reside underdrawable-v23
too, but lets follow the pattern of original source locations for now). Note, that file's@dimen/highlight_alpha_material_colored
is picked up fromappcompat-v7
, if you use one :) If not, you can reffer it's value from it:The solution is not the best as you need to bring over files you don't originally own. Also, you might want to monitor the possible updates to v23 for any future changes. But at least the changes are contained to v23 only.
With minimal effort I was able to fix this by building a custom background for the spinner.
Using
AppCompatSpinner
I had to create 2 xmls for the background, let's call thisspinner_background.xml
:1. First one goes to the
drawable
folder and looks like this,spinner_background.xml
:Where
selector_background_borderless
is a plain selector like(I added the minimal items you need, you could explore it's ripple alternative for v21+. In fact I would recommend you to do so):And
bg_spinner_anchor
is a 9patch PNG for the caret. I used these assets: bg_spinner_anchor2. The second one goes to the
drawable-v23
folder to properly support ripple and looks like this,spinner_background.xml
:Where
ic_spinner_caret
is a vector used from the Android source code looking like this. You should add also add this to yourdrawable-v23
folder:Credits go to alanv from the Android UI toolkit for Guidance!