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:
Using AppCompatSpinner from the support library does not change the behaviour. Support library version used is 23.1.1
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 this spinner_background.xml
:
1. First one goes to the drawable
folder and looks like this, 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>
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):
<?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>
And bg_spinner_anchor
is a 9patch PNG for the caret. I used these assets: bg_spinner_anchor
2. The second one goes to the drawable-v23
folder to properly support ripple and looks like this, 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>
Where ic_spinner_caret
is a vector used from the Android source code looking like this. You should add also add this to your drawable-v23
folder:
<?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>
Credits go to alanv from the Android UI toolkit for Guidance!