Comment définir un thème différent pour la liste déroulante d'un Spinner?

102

Un exemple d'utilisation:

entrez la description de l'image ici

Le Spinner a un thème sombre, mais je veux que le menu déroulant soit sur le thème de la lumière.

Chris Banes
la source

Réponses:

195

Android M

Nouveauté d'Android 6.0, Spinner dispose désormais du android:popupThemeparamètre qui vous permet de définir le thème utilisé pour le popup (menu déroulant).

Vous pouvez l'utiliser comme ceci:

<Spinner
    android:layout_height="wrap_content"
    android:layout_width="match_parent"
    android:popupTheme="@android:style/ThemeOverlay.Material.Light" />

Cela fonctionnera sur les appareils exécutant le niveau d'API 23+, mais pas sur les appareils exécutant une version inférieure d'Android.

AppCompat

C'est là qu'AppCompat entre en jeu. Son implémentation Spinner prend également en charge popupTheme, mais il est un peu plus compliqué de bien faire.

<Spinner
    android:layout_height="wrap_content"
    android:layout_width="match_parent"
    app:popupTheme="@style/ThemeOverlay.AppCompat.Light" />

Après cela, vous devez mettre à jour votre adaptateur pour pouvoir travailler avec AppCompat. Vous faites cela en lui faisant implémenter la nouvelle ThemedSpinnerAdapterinterface.

public class MyAdapter extends BaseAdapter implements ThemedSpinnerAdapter {

   Theme getDropDownViewTheme() { ... }

   void setDropDownViewTheme(Theme theme) { ... }

}

Ces méthodes sont utilisées par Spinner pour pouvoir indiquer à l'adaptateur quel thème utiliser pour gonfler les vues déroulantes. Pour rendre cela aussi simple que possible, nous vous avons donné une Helperclasse que vous pouvez brancher sur votre adaptateur.

Cela signifie que votre adaptateur devient quelque chose comme:

public class MyAdapter extends BaseAdapter implements ThemedSpinnerAdapter {
  private final ThemedSpinnerAdapter.Helper mDropDownHelper;

  public MyAdapter(Context context) { 
    mDropDownHelper = new ThemedSpinnerAdapter.Helper(context);
  }

  @Override
  public View getDropDownView(int position, View convertView, ViewGroup parent) {
    View view;

    if (convertView == null) {
      // Inflate the drop down using the helper's LayoutInflater
      LayoutInflater inflater = mDropDownHelper.getDropDownViewInflater();
      view = inflater.inflate(R.layout.my_dropdown, parent, false);
    }

    // ...

    return view;
  }

  @Override
  public void setDropDownViewTheme(Theme theme) {
    mDropDownHelper.setDropDownViewTheme(theme);
  }

  @Override
  public Theme getDropDownViewTheme() {
    return mDropDownHelper.getDropDownViewTheme();
  }
}
Chris Banes
la source
Salut, je n'ai pas trouvé ThemedSpinnerAdapter dans l'appcompat-v7. J'utilise la version 22.2.1. Dois-je faire quelque chose de différent pour l'importer?
Douglas Alves
3
@DouglasAlves utilise le plus récent 23.0.0
khusrav
Il semble qu'Android Studio ne connaisse pas l'application: attribut popupTheme Spinner: "Préfixe d'espace de noms inattendu" app "trouvé pour la balise Spinner". Lint échoue également avec la même erreur.
makovkastar
1
@Chris Banes: il donne la liste déroulante avec un fond sombre, quel que soit le thème que vous utilisez.
Ashwin le
2
devrait-il utiliser "android.support.v7.widget.AppCompatSpinner" au lieu de "spinner" dans le xml?
Angel Koh
2

pour la flèche de spinner que j'ai utilisée, android:backgroundTint="@color/white"cela fonctionnera à partir de l'API 21

pour la vue spinner et la vue déroulante:

ArrayAdapter<Area> areasAdapter = new ArrayAdapter<Area>(getContext(),R.layout.spinner_item, areas);

areasAdapter.setDropDownViewResource(R.layout.dropdwon_item);
areasSpinner.setAdapter(areasAdapter);

pour getView () l'adaptateur utilisera spinner_item.xml

pour getDropDownView (), l'adaptateur utilisera dropdwon_item.xml

alors vous pouvez utiliser vos mises en page personnalisées comme vous le souhaitez

J'espère que ça aide

bsma
la source
0

Juste pour référence si vous utilisez CursorAdaptervotre implémentation peut être beaucoup plus facile, il suffit de remplacer newView(), pas besoin de remplacer getDropDownView()ici:

@Override
public View newView(Context context, Cursor cursor, ViewGroup parent) {
    return mDropDownHelper.getDropDownViewInflater().inflate(R.layout.list_item, parent, false);
}
rekire
la source
-6

vous pouvez essayer ceci: dans votre dossier de mise en page, créez un spinner_item.xml:

<TextView 
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="right"
android:padding="10dp"
android:background = "#ffffff"
android:textColor="@color/primary_text"
android:textSize="@dimen/text_size_normal" />

puis utilisez ce code:

spinnerAdapter = new ArrayAdapter<String>(R.layout.spinner_item,items);
Ahmad Azarnia
la source
6
Je suppose que parce que c'est assez évident, cela ne répond pas à la question. La question est de définir un thème, je ne vois aucune référence à la thématisation dans cette réponse. Juste pour que nous soyons clairs, je n'ai pas voté contre cela, d'autres y sont déjà suffisamment allés.
2Dee