Spinners provide two states. The first and default state (state A) shows the currently selected value. The second (state B) shows a dropdown menu when the spin
State A takes on the following style:
// Theme (Base) // Theme.AppCompat
@android:style/Widget.TextView.SpinnerItem
// Holo & Holo Light
@android:style/Widget.Holo.TextView.SpinnerItem
The attribute at play here is spinnerItemStyle
.
Moreover, the padding provided is not paddingLeft
, but paddingStart
- to support LTR & RTL languages. Similarly, paddingEnd
is set instead of paddingRight
. This info applies to API >=17.
If you are using AppCompat, you will still override the spinnerItemStyle
attribute, but provide paddingLeft
and paddingRight
.
Example:
<style name="Theme.App.Base" parent="Theme.App">
...
<item name="android:spinnerItemStyle">@style/TextViewSpinnerItem</item>
</style>
<style name="TextViewSpinnerItem" parent="@android:style/Widget.TextView.SpinnerItem">
<item name="android:paddingLeft">40dp</item>
<item name="android:paddingRight">40dp</item>
</style>
The 40dp
value is for testing if setting this style even works. This should only pad State A
(with 40dp), leaving State B
with default padding of 8dp
. Once confirmed, you can make it 0dp
, or as per your requirement.
This is the result I get:
Update:
In reference to the sample project - MainActivity
:
spinner.setAdapter(ArrayAdapter.createFromResource(this,
R.array.planets_array, android.R.layout.simple_spinner_item));
By giving the adapter android.R.layout.simple_spinner_item
, you are telling it to use the layout for both State A and State B. This is a problem because of the way this layout is defined:
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@android:id/text1"
style="?android:attr/spinnerItemStyle"
android:singleLine="true"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ellipsize="marquee"
android:textAlignment="inherit"/>
Notice the style
applied to this TextView
. Earlier, I had suggested that you override this attribute. And it worked. But since this layout is used for both the states, the outcome is not as desired.
In fact, the statement right above (though not doing anything at the moment) is more promising:
ArrayAdapter.createFromResource(this,
R.array.planets_array, android.R.layout.simple_spinner_item)
.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
By using setDropDownViewResource(int)
, you will allow the possibility of introducing different style attributes. In this case, State A will be represented by android.R.layout.simple_spinner_item
and State B will use android.R.layout.simple_spinner_dropdown_item
.
Let's take a look at android.R.layout.simple_spinner_dropdown_item
:
<CheckedTextView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@android:id/text1"
style="?android:attr/spinnerDropDownItemStyle"
android:singleLine="true"
android:layout_width="match_parent"
android:layout_height="?android:attr/dropdownListPreferredItemHeight"
android:ellipsize="marquee"/>
Now we can override another attribute - spinnerDropDownItemStyle
- and give State B a whole different look. But, we won't. On Lollipop, spinnerDropDownItemStyle
points to style Widget.Material.DropDownItem.Spinner
which sets the paddingX
to 8dp
. And you said that you're okay with the default padding in State B.
So, here's what you need:
// Create an ArrayAdapter
ArrayAdapter<CharSequence> mAdapter = ArrayAdapter.createFromResource(this,
R.array.planets_array, android.R.layout.simple_spinner_item);
// State B
mAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
AND, if you don't have this already, add it to values/styles.xml:
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
<item name="android:spinnerItemStyle">@style/TextViewSpinnerItem</item>
</style>
<style name="TextViewSpinnerItem" parent="@android:style/Widget.TextView.SpinnerItem">
<item name="android:paddingLeft">0dp</item>
<item name="android:paddingRight">0dp</item>
</style>
You should also create values-v21/styles.xml
and add:
<style name="TextViewSpinnerItem" parent="@android:style/Widget.Material.TextView.SpinnerItem">
<item name="android:paddingLeft">0dp</item>
<item name="android:paddingRight">0dp</item>
</style>