7

I filatori forniscono due stati. Il primo e lo stato predefinito (stato A) mostra il valore attualmente selezionato. Il secondo (stato B) mostra un menu a discesa quando viene toccata la finestra di selezione.Personalizzazione della spaziatura dei filatori

State A and B example

Per impostazione predefinita un padding sinistro si aggiunge agli elementi visualizzati in stato di A e B. vorrei rimuoverla quando viene visualizzato il valore corrente selezionato (stato A), ma per mantenerlo quando le voci sono visualizzate nel menu a discesa (stato B).

Dal momento che l'imbottitura è impostata con il CheckedTextView utilizzati nel layout specificato quando viene creata la filatrice, il mio primo tentativo è stato quello di passare al costruttore filatore un layout personalizzato che contiene un CheckedTextView con imbottitura vuoto. In questo modo, i disapears padding sinistro nello Stato A, ma anche in stato B. Tuttavia, il mio obiettivo era di tenerlo per lo stato A.

Il mio secondo tentativo è stato quello di personalizzare Android: dropDownSpinnerStyle nella mia definizione del tema. Poiché si modifica il colore di sfondo per Android : dropDownSpinnerStyle cambia il colore di sfondo dell'elemento solo nello stato A, il mio pensiero era di ignorare marginLeft o paddingLeft con un valore negativo. Sfortunatamente, non ha alcun effetto.

Dato che il margine negativo/padding sembra non essere preso in considerazione, ho provato il contrario. In primo luogo, ho usato un layout personalizzato (come spiegato per il mio primo tentativo) per rimuovere il riempimento sinistro su entrambi gli stati (A e B). In secondo luogo, ho definito uno stile personalizzato per la proprietà android: dropDownListViewStyle. Sfortunatamente, l'utilizzo di un valore di margine positivo sinistro con l'ultima proprietà non ha alcun effetto. Quindi, ho impostato paddingLeft. Funziona e mi consente di ottenere la spaziatura sinistra solo per lo stato B. Tuttavia, lo spazio sinistro si applica anche al colore del tocco di sfondo (vedi immagine sotto).

enter image description here

Credo che solo lo stile per lo stato A deve essere modificato se voglio avere il colore di sfondo sul touch che riempie completamente la larghezza del menu a discesa. Qualsiasi idea, suggerimento o esempio è accolto favorevolmente.

Qui di seguito è la mia definizione del tema per il terzo tentativo:

<style name="Theme.App.Base" parent="Theme.App"> 
    ... 
    <item name="android:dropDownListViewStyle">@style/Widget.Spinner.DropDown.ListView</item> 
</style> 

<style name="Widget.Spinner.DropDown.ListView" parent="Widget.AppCompat.ListView.DropDown"> 
    <item name="android:paddingLeft">16dp</item> 
</style> 
+0

Hai provato? http://stackoverflow.com/questions/16694786/how-to-customize-a-spinner-in-android – jyoon

risposta

30

Stato A assume il seguente stile:

// Theme (Base) // Theme.AppCompat 
@android:style/Widget.TextView.SpinnerItem 

// Holo & Holo Light 
@android:style/Widget.Holo.TextView.SpinnerItem 

L'attributo in gioco qui è spinnerItemStyle.

Inoltre, l'imbottitura è fornito nonpaddingLeft, ma paddingStart - sostenere lingue LTR & RTL. Allo stesso modo, paddingEnd è impostato al posto di paddingRight. Queste informazioni si applicano a API> = 17.

Se si utilizza AppCompat, si sostituirà comunque l'attributo spinnerItemStyle, ma fornire paddingLeft e paddingRight.

Esempio:

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

Il valore 40dp serve a verificare se l'impostazione di questo stile anche funziona. Questo dovrebbe solo pagare State A (con 40dp), lasciando State B con padding predefinito di 8dp. Una volta confermato, puoi renderlo 0dp o secondo il tuo requisito.

questo è il risultato che ottengo:

enter image description here

Aggiornamento:

In riferimento al progetto di esempio - MainActivity:

spinner.setAdapter(ArrayAdapter.createFromResource(this, 
      R.array.planets_array, android.R.layout.simple_spinner_item)); 

Dando l'adattatore android.R.layout.simple_spinner_item, stai dicendo di usare il layout per sia Stato A e B. Stato Questo è un problema a causa del modo questo layout è definito:

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

comunicazione la style applicato a questo TextView. In precedenza, avevo suggerito di ignorare questo attributo. E ha funzionato. Ma dal momento che questo layout è utilizzato per entrambi gli stati, il risultato non è quello desiderato.

Infatti, la dichiarazione proprio sopra (anche se non fare nulla per il momento) è più promettente:

ArrayAdapter.createFromResource(this, 
      R.array.planets_array, android.R.layout.simple_spinner_item) 
      .setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); 

Utilizzando setDropDownViewResource(int), si consente la possibilità di introdurre diversi attributi di stile. In questo caso, lo stato A sarà rappresentato da android.R.layout.simple_spinner_item e lo stato B utilizzerà android.R.layout.simple_spinner_dropdown_item.

Diamo uno sguardo a 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"/> 

Ora possiamo ignorare un altro attributo - spinnerDropDownItemStyle - e dare lo Stato B nel suo complesso aspetto diverso. Ma non lo faremo. Su Lollipop, spinnerDropDownItemStyle indica lo stile Widget.Material.DropDownItem.Spinner che imposta paddingX su 8dp. E tu hai detto che stai bene con l'imbottitura di default nello Stato B.

Quindi, ecco quello che vi serve:

// 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); 

E, se non si dispone di questo già, aggiungerlo ai valori/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> 

È inoltre necessario creare values-v21/styles.xml e aggiungere:

<style name="TextViewSpinnerItem" parent="@android:style/Widget.Material.TextView.SpinnerItem"> 
    <item name="android:paddingLeft">0dp</item> 
    <item name="android:paddingRight">0dp</item> 
</style> 
+0

Grazie per l'aiuto. Sfortunatamente, il tuo esempio aggiorna gli stati A e B quando viene applicato su Android Lollipop. – Laurent

+0

@Laurent Ho aggiunto uno screenshot del codice che ho provato. Il codice è in esecuzione nell'emulatore di anteprima di Genymotion Lollipop.Non sono sicuro del motivo per cui non sta lavorando alla tua parte. Qual è il tuo tema di base? Potresti postare tutte le parti rilevanti del tuo 'styles.xml'? – Vikram

+0

Ho creato un semplice progetto per riprodurre il problema. 'Styles.xml' è disponibile su https://github.com/lpellegr/android-spinner-styling-issue/blob/master/app/src/main/res/values/styles.xml – Laurent