Cómo personalizar un Spinner en Android

140

Quiero agregar una altura personalizada al menú desplegable de un Spinner, digamos 30dp, y quiero ocultar los divisores de la lista desplegable de Spinner.

Hasta ahora intenté implementar el siguiente estilo para 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>

y el código de mi ruleta es:

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

Pero nada parece estar funcionando.

Shruti
fuente
Ninguno de los estilos se aplica? popupBackGround o cualquier otra cosa? Extraño.
Chintan Soni
@Houcine: ya probé esos ejemplos ... quiero ajustar la altura de la lista desplegable
Shruti
@ shree202: no se aplica estilo
Shruti
1
@ComeIn, no es un estilo de Android, sino uno personalizado que creó. Es por eso que solo tiene "style ="
CyberClaw

Respuestas:

194

Cree un adaptador personalizado con un diseño personalizado para su ruleta.

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

En los estilos, agregue sus dimensiones y altura personalizadas según sus necesidades.

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

  </style>

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

  </style>
Tarun
fuente
3
Intenta cambiar <item name="android:height"> a<item name="android:layout_height">
Tarun
1
gracias por responder ... intentado pero sin efecto ... trabajando encendido / apagado durante los últimos 3-4 días ... Ahora me
estoy
55
@Tarun, ¿no lo necesitas android:id="@+android:id/text1"en el archivo simple_spinner_dropdown_item.xml?
Batbrat
1
En R.layout.simple_spinner_dropdown_item, cambie el valor de android: layout_height a "? Attr / dropdownListPreferredItemHeight" o obtendrá un error: "Error: El atributo no es público"
Loenix
9
Para futuros visitantes a esta respuesta : no envuelva TextView y CheckedTextview dentro de un diseño . Publíquelo directamente en su archivo layout_file.xml. Estuve atrapado aquí durante algunas horas hasta que descubrí cuál fue el error.
Francisco Romero
95

Puede crear un diseño giratorio totalmente personalizado como

Paso 1: en la carpeta dibujable, crea background.xml para un borde de la ruleta.

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

Paso 2: para el diseño del diseño de la ruleta, use este icono desplegable o cualquier imagen drop.png ingrese la descripción de la imagen aquí

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

Finalmente se ve como la imagen de abajo y se puede hacer clic en todas partes en el área redonda y no es necesario escribir, haga clic en Lister para imageView.

ingrese la descripción de la imagen aquí

Paso 3: para el diseño desplegable, elimine la línea de la vista de lista desplegable y cambie el color de fondo, cree un adaptador personalizado como

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

En la carpeta de diseño, cree 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"
/>

En la carpeta de diseño, cree 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" />

En los estilos, puede agregar dimensiones y altura personalizadas según sus necesidades.

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

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

Finalmente se ve como

ingrese la descripción de la imagen aquí

De acuerdo con el requisito, puede cambiar el color de fondo y el texto del color desplegable cambiando el color de fondo o el color de texto de simple_spinner_dropdown.xml

Binesh Kumar
fuente
en el primer código recortado, ¿quieres decir android: height = "1dp" en la línea 6?
Willi Mentzel
Por error, escribe dos veces android: width = "1dp"
Binesh Kumar
2
No hay problema, simplemente no quería editarlo yo mismo porque no estaba seguro, si querías especificar la altura con "1dp" o si era solo un duplicado. buena respuesta sin embargo. :)
Willi Mentzel
@BineshKumar Hola, ¿puedo saber dónde declaraste CheckedTextView? Porque cuando pegué el código, me dijo que el elemento debe declararse primero
hyperfkcb
2
Hombre, podrías haber usado nombres en tus diseños y dibujos, he pasado media hora y todavía no tengo idea de qué hacer. Menos por mala respuesta.
Anton Kizema
21

La solución más elegante y flexible que he encontrado hasta ahora está aquí: http://android-er.blogspot.sg/2010/12/custom-arrayadapter-for-spinner-with.html

Básicamente, siga estos pasos:

  1. Cree un archivo xml de diseño personalizado para su elemento desplegable, digamos que lo llamaré spinner_item.xml
  2. Cree una clase de vista personalizada para su adaptador desplegable. En esta clase personalizada, debe sobrescribir y establecer su diseño de elemento desplegable personalizado en el método getView () y getDropdownView (). Mi código es el siguiente:

    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. En su actividad o fragmento, utilice el adaptador personalizado para su vista giratoria. Algo como esto:

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

donde opciones es la lista de cadenas de elementos desplegables.

Tony Vu
fuente
El truco para mí fue anular getDropDownView, estaba anulando getView, pero no me di cuenta de que tenía que anular ese método.
estebanuri
7

Prueba esto

Estaba enfrentando muchos problemas cuando estaba probando otra solución ...... Después de mucha I + D ahora obtuve la solución

  1. cree custom_spinner.xml en la carpeta de diseño y pegue este código

     <?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. en tu actividad

    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. crear una nueva clase de adaptador

    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
fuente
Esto me dio la imagen men_icon en todos los artículos después de hacer clic en la ruleta, que no era lo que estaba buscando. Si no desea que la imagen men_icon (u otras personalizaciones) aparezca en todas las filas después de hacer clic en el control giratorio, elimine la anulación "getDropDownView".
Brettins
2

Esto funcionó para mí:

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

y en mi carpeta de diseño creé 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
fuente
0

He creado un pequeño proyecto de demostración sobre esto, podría echarle un vistazo Enlace al proyecto

Vivek Barai
fuente