Comment personnaliser un Spinner sous Android

140

Je veux ajouter une hauteur personnalisée à la liste déroulante de Spinner, disons 30dp, et je veux masquer les diviseurs de la liste déroulante de Spinner.

Jusqu'à présent, j'ai essayé d'implémenter le style suivant au Spinner:

<style name="spinner_style">
        <item name="android:paddingLeft">0dp</item>
        <item name="android:dropDownWidth">533dp</item>
        <item name="android:showDividers">none</item>
        <item name="android:dividerHeight">0dp</item>
        <item name="android:popupBackground">@drawable/new_bg</item>
        <item name="android:dropDownHeight">70dp</item>
        <item name="android:scrollbarAlwaysDrawVerticalTrack">true</item>
        <item name="android:dropDownSelector">@android:color/white</item>
 </style>

et le code de mon spinner est:

<Spinner
            android:id="@+id/pioedittxt5"
            android:layout_width="543dp"
            android:layout_height="63dp"
            android:layout_toRightOf="@+id/piotxt5"
            android:background="@drawable/spinner"
            style="@style/spinner_style"
            android:dropDownVerticalOffset="-53dp"
            android:spinnerMode="dropdown"
            android:drawSelectorOnTop="true"
            android:entries="@array/travelreasons"
            android:prompt="@string/prompt" />

Mais rien ne semble fonctionner.

Shruti
la source
Aucun des styles n'est appliqué? popupBackGround ou autre chose? Étrange.
Chintan Soni
@Houcine: j'ai déjà essayé ces exemples .. je veux ajuster la hauteur de la liste déroulante
Shruti
@ shree202: aucun style ne s'applique
Shruti
1
@ComeIn, ce n'est pas un style Android, mais un style personnalisé qu'il a créé. C'est pourquoi il vient de "style ="
CyberClaw

Réponses:

194

Créez un adaptateur personnalisé avec une disposition personnalisée pour votre spinner.

Spinner spinner = (Spinner) findViewById(R.id.pioedittxt5);
ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource(this,
        R.array.travelreasons, R.layout.simple_spinner_item);
adapter.setDropDownViewResource(R.layout.simple_spinner_dropdown_item);
spinner.setAdapter(adapter);

R.layout.simple_spinner_item

<TextView xmlns:android="http://schemas.android.com/apk/res/android" 
    android:id="@android:id/text1"
    style="@style/spinnerItemStyle"
    android:maxLines="1"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:ellipsize="marquee" />

R.layout.simple_spinner_dropdown_item

<CheckedTextView xmlns:android="http://schemas.android.com/apk/res/android" 
    android:id="@android:id/text1"
    style="@style/spinnerDropDownItemStyle"
    android:maxLines="1"
    android:layout_width="match_parent"
    android:layout_height="?android:attr/dropdownListPreferredItemHeight"
    android:ellipsize="marquee" />

Dans les styles, ajoutez vos dimensions et hauteur personnalisées selon vos besoins.

 <style name="spinnerItemStyle" parent="android:Widget.TextView.SpinnerItem">

  </style>

  <style name="spinnerDropDownItemStyle" parent="android:TextAppearance.Widget.TextView.SpinnerItem">

  </style>
Tarun
la source
3
Essayez de changer <item name="android:height"> pour<item name="android:layout_height">
Tarun
1
merci d'avoir répondu ... essayé mais sans effet ... travailler dessus / éteindre pendant les 3-4 derniers jours .. Je
suis
5
@Tarun, n'avez-vous pas besoin android:id="@+android:id/text1"du fichier simple_spinner_dropdown_item.xml?
batbrat
1
Dans R.layout.simple_spinner_dropdown_item, changez la valeur android: layout_height en "? Attr / dropdownListPreferredItemHeight" ou vous obtiendrez une erreur: "Erreur: l'attribut n'est pas public"
Loenix
9
Pour les futurs visiteurs de cette réponse : n'emballez pas TextView et CheckedTextview dans une mise en page . Publiez-le directement dans votre fichier layout_file.xml. Je suis resté coincé ici pendant quelques heures jusqu'à ce que je découvre quelle était l'erreur.
Francisco Romero
95

Vous pouvez créer un design de spinner entièrement personnalisé comme

Étape 1: Dans le dossier drawable, créez background.xml pour une bordure du spinner.

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="@android:color/transparent" />
<corners android:radius="5dp" />
<stroke
android:width="1dp"
   android:color="@android:color/darker_gray" />
</shape>

Étape 2: pour la conception de la mise en page du spinner, utilisez cette icône déroulante ou n'importe quelle image drop.png entrez la description de l'image ici

 <RelativeLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_marginRight="3dp"
    android:layout_weight=".28"
    android:background="@drawable/spinner_border"
    android:orientation="horizontal">

    <Spinner
        android:id="@+id/spinner2"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_centerVertical="true"
        android:layout_gravity="center"
        android:background="@android:color/transparent"
        android:gravity="center"
        android:layout_marginLeft="5dp"
        android:spinnerMode="dropdown" />

    <ImageView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentRight="true"
        android:layout_centerVertical="true"
        android:layout_gravity="center"
        android:src="@mipmap/drop" />

</RelativeLayout>

Enfin ressemble à l'image ci-dessous et il est partout cliquable dans la zone ronde et pas besoin d'écrire cliquez sur Lister pour imageView.

entrez la description de l'image ici

Étape 3: Pour la conception déroulante, supprimez la ligne de la liste déroulante et modifiez la couleur d'arrière-plan, créez un adaptateur personnalisé comme

Spinner spinner = (Spinner) findViewById(R.id.spinner1);
String[] years = {"1996","1997","1998","1998"};
ArrayAdapter<CharSequence> langAdapter = new ArrayAdapter<CharSequence>(getActivity(), R.layout.spinner_text, years );
langAdapter.setDropDownViewResource(R.layout.simple_spinner_dropdown);
mSpinner5.setAdapter(langAdapter);

Dans le dossier layout, créez R.layout.spinner_text.xml

<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:layoutDirection="ltr"
android:id="@android:id/text1"
style="@style/spinnerItemStyle"
android:singleLine="true"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ellipsize="marquee"
android:paddingLeft="2dp"
/>

Dans le dossier layout, créez simple_spinner_dropdown.xml

<?xml version="1.0" encoding="utf-8"?>
<CheckedTextView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@android:id/text1"
style="@style/spinnerDropDownItemStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ellipsize="marquee"
android:paddingBottom="5dp"
android:paddingLeft="10dp"
android:paddingRight="10dp"
android:paddingTop="5dp"
android:singleLine="true" />

Dans les styles, vous pouvez ajouter des dimensions et une hauteur personnalisées selon vos besoins.

<style name="spinnerItemStyle" parent="android:Widget.TextView.SpinnerItem">
</style>

<style name="spinnerDropDownItemStyle" parent="android:TextAppearance.Widget.TextView.SpinnerItem">
</style>

Ressemble enfin à

entrez la description de l'image ici

Selon l'exigence, vous pouvez changer la couleur d'arrière-plan et le texte de la couleur déroulante en changeant la couleur d'arrière-plan ou la couleur du texte de simple_spinner_dropdown.xml

Binesh Kumar
la source
dans le premier code extrait, voulez-vous dire android: height = "1dp" à la ligne 6?
Willi Mentzel
Par erreur, écrivez deux fois android: width = "1dp"
Binesh Kumar
2
Pas de problème, je ne voulais simplement pas le modifier moi-même parce que je n'étais pas sûr, si vous vouliez spécifier la hauteur avec "1dp" ou s'il s'agissait simplement d'un double. bonne réponse cependant. :)
Willi Mentzel
@BineshKumar Hey, puis-je savoir où vous avez déclaré CheckedTextView? Parce que quand j'ai collé le code, il m'a dit que l'élément devait être déclaré en premier
hyperfkcb
2
Mec, vous auriez pu utiliser des noms dans vos mises en page et vos dessins, j'ai passé une demi-heure et je ne sais toujours pas quoi faire. Moins pour une mauvaise réponse.
Anton Kizema
21

La solution la plus élégante et la plus flexible que j'ai trouvée jusqu'à présent est ici: http://android-er.blogspot.sg/2010/12/custom-arrayadapter-for-spinner-with.html

En gros, suivez ces étapes:

  1. Créez un fichier xml de mise en page personnalisée pour votre élément de liste déroulante, disons que je l'appellerai spinner_item.xml
  2. Créez une classe de vue personnalisée, pour votre adaptateur de liste déroulante. Dans cette classe personnalisée, vous devez remplacer et définir votre disposition d'élément de liste déroulante personnalisée dans les méthodes getView () et getDropdownView (). Mon code est comme ci-dessous:

    public class CustomArrayAdapter extends ArrayAdapter<String>{
    
    private List<String> objects;
    private Context context;
    
    public CustomArrayAdapter(Context context, int resourceId,
         List<String> objects) {
         super(context, resourceId, objects);
         this.objects = objects;
         this.context = context;
    }
    
    @Override
    public View getDropDownView(int position, View convertView,
        ViewGroup parent) {
        return getCustomView(position, convertView, parent);
    }
    
    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
      return getCustomView(position, convertView, parent);
    }
    
    public View getCustomView(int position, View convertView, ViewGroup parent) {
    
    LayoutInflater inflater=(LayoutInflater) context.getSystemService(  Context.LAYOUT_INFLATER_SERVICE );
    View row=inflater.inflate(R.layout.spinner_item, parent, false);
    TextView label=(TextView)row.findViewById(R.id.spItem);
     label.setText(objects.get(position));
    
    if (position == 0) {//Special style for dropdown header
          label.setTextColor(context.getResources().getColor(R.color.text_hint_color));
    }
    
    return row;
    }
    
    }
  3. Dans votre activité ou fragment, utilisez l'adaptateur personnalisé pour votre vue double. Quelque chose comme ça:

    Spinner sp = (Spinner)findViewById(R.id.spMySpinner);
    ArrayAdapter<String> myAdapter = new CustomArrayAdapter(this, R.layout.spinner_item, options);
    sp.setAdapter(myAdapter);

où options est la liste des chaînes d'élément de liste déroulante.

Tony Vu
la source
L'astuce pour moi était de remplacer getDropDownView, je remplaçais getView, mais je ne réalisais pas que je devais remplacer cette méthode.
estebanuri
7

Essaye ça

J'étais confronté à de nombreux problèmes lorsque j'essayais une autre solution ... Après beaucoup de R&D, j'ai maintenant une solution

  1. créez custom_spinner.xml dans le dossier layout et collez ce code

     <?xml version="1.0" encoding="utf-8"?>
    <RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@color/colorGray">
    <TextView
    android:id="@+id/tv_spinnervalue"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:textColor="@color/colorWhite"
    android:gravity="center"
    android:layout_alignParentLeft="true"
    android:textSize="@dimen/_18dp"
    android:layout_marginTop="@dimen/_3dp"/>
    <ImageView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_alignParentRight="true"
    android:background="@drawable/men_icon"/>
    </RelativeLayout>
  2. dans votre activité

    Spinner spinner =(Spinner)view.findViewById(R.id.sp_colorpalates);
    String[] years = {"1996","1997","1998","1998"};
    spinner.setAdapter(new SpinnerAdapter(this, R.layout.custom_spinner, years));
  3. créer une nouvelle classe d'adaptateur

    public class SpinnerAdapter extends ArrayAdapter<String> {
    private String[] objects;
    
    public SpinnerAdapter(Context context, int textViewResourceId, String[] objects) {
        super(context, textViewResourceId, objects);
        this.objects=objects;
    }
    
    @Override
    public View getDropDownView(int position, View convertView, @NonNull ViewGroup parent) {
        return getCustomView(position, convertView, parent);
    }
    
    @NonNull
    @Override
    public View getView(int position, View convertView, @NonNull ViewGroup parent) {
        return getCustomView(position, convertView, parent);
    }
    
    private View getCustomView(final int position, View convertView, ViewGroup parent) {
        View row = LayoutInflater.from(parent.getContext()).inflate(R.layout.custom_spinner, parent, false);
        final TextView label=(TextView)row.findViewById(R.id.tv_spinnervalue);
        label.setText(objects[position]);
        return row;
    }
    }
Sunil
la source
Cela m'a donné l'image men_icon sur tous les éléments après avoir cliqué sur le spinner, ce qui n'était pas ce que je recherchais. Si vous ne voulez pas que l'image men_icon (ou d'autres personnalisations) apparaisse sur toutes les lignes après avoir cliqué sur la double flèche, supprimez le remplacement "getDropDownView".
Brettins
2

Cela a fonctionné pour moi:

ArrayAdapter<String> adapter = new ArrayAdapter<String>(getActivity(),R.layout.simple_spinner_item,areas);
            Spinner areasSpinner = (Spinner) view.findViewById(R.id.area_spinner);
            areasSpinner.setAdapter(adapter);

et dans mon dossier de mise en page, j'ai créé simple_spinner_item:

<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@android:id/text1"
android:layout_width="match_parent"
// add custom fields here 
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceListItemSmall"
android:gravity="center_vertical"
android:paddingStart="?android:attr/listPreferredItemPaddingStart"
android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
android:minHeight="?android:attr/listPreferredItemHeightSmall"
android:paddingLeft="?android:attr/listPreferredItemPaddingLeft"
android:paddingRight="?android:attr/listPreferredItemPaddingRight" />
zizoujab
la source
0

J'ai construit un petit projet de démonstration à ce sujet, vous pouvez y jeter un œil Lien vers le projet

Vivek Barai
la source