¿Cómo establecer el valor predeterminado de Spinner en nulo?

Estoy tratando de cargar un Spinner sin ningún valor seleccionado. Una vez que el usuario selecciona un valor, los lleva a otra página.

Esto está demostrando ser un problema porque en la actualidad, la página simplemente se carga enseguida antes de que el usuario tenga la opción de elegir.

Mi clase spinner está configurada de la misma manera que la de Google: http://developer.android.com/resources/tutorials/views/hello-spinner.html

Entonces, básicamente, ¿es posible tener una ruleta que cargue sin nada seleccionado porque actualmente carga el primer elemento en mi matriz de cuerdas?

¿es posible tener un girador que carga con nada seleccionado

Solo si no hay datos Si tiene 1+ elementos en SpinnerAdapter , el Spinner siempre tendrá una selección.

Spinners no están diseñados para ser widgets de comando. Los usuarios no esperan una selección en un Spinner para comenzar una actividad. Considere usar otra cosa, como ListView o GridView , en lugar de un Spinner .


EDITAR

Por cierto, se me olvidó mencionar que siempre puede poner una entrada adicional en su adaptador que representa “sin selección” y convertirlo en el elemento inicial seleccionado en el Spinner .

Alternativamente, puede anular su adaptador giratorio y proporcionar una vista vacía para la posición 0 en su método getView y una vista con altura 0dp en el método getDropDownView .

De esta manera, tiene un texto inicial como “Seleccione una opción …” que aparece cuando se carga por primera vez la ruleta, pero no es una opción que el usuario puede elegir (técnicamente lo es, pero porque la altura es 0 , ellos no pueden verlo).

Esta es una implementación completa de la idea de Paul Bourdeaux , es decir, devolver una vista inicial especial (o una vista vacía) en getView() para la posición 0.

Funciona para mí y es relativamente sencillo. Puede considerar este enfoque especialmente si ya tiene un adaptador personalizado para su Spinner. (En mi caso, estaba usando un adaptador personalizado para personalizar fácilmente el diseño de los elementos, cada elemento tiene un par de TextViews).

El adaptador sería algo así:

 public class MySpinnerAdapter extends ArrayAdapter { public MySpinnerAdapter(Context context, List items) { super(context, R.layout.my_spinner_row, items); } @Override public View getDropDownView(int position, View convertView, @NonNull ViewGroup parent) { if (position == 0) { return initialSelection(true); } return getCustomView(position, convertView, parent); } @NonNull @Override public View getView(int position, View convertView, @NonNull ViewGroup parent) { if (position == 0) { return initialSelection(false); } return getCustomView(position, convertView, parent); } @Override public int getCount() { return super.getCount() + 1; // Adjust for initial selection item } private View initialSelection(boolean dropdown) { // Just an example using a simple TextView. Create whatever default view // to suit your needs, inflating a separate layout if it's cleaner. TextView view = new TextView(getContext()); view.setText(R.string.select_one); int spacing = getContext().getResources().getDimensionPixelSize(R.dimen.spacing_smaller); view.setPadding(0, spacing, 0, spacing); if (dropdown) { // Hidden when the dropdown is opened view.setHeight(0); } return view; } private View getCustomView(int position, View convertView, ViewGroup parent) { // Distinguish "real" spinner items (that can be reused) from initial selection item View row = convertView != null && !(convertView instanceof TextView) ? convertView : LayoutInflater.from(getContext()).inflate(R.layout.my_spinner_row, parent, false); position = position - 1; // Adjust for initial selection item MyModel item = getItem(position); // ... Resolve views & populate with data ... return row; } } 

Eso es. Tenga en cuenta que si usa un OnItemSelectedListener con su Spinner, en onItemSelected() también tendría que ajustar la position para tener en cuenta el elemento predeterminado, por ejemplo:

 if (position == 0) { return; } else { position = position - 1; } MyModel selected = items.get(position); 

En mi caso, aunque el tamaño ‘2’ se muestra en la ruleta, ¡no pasa nada hasta que se hace una selección!

Tengo un archivo xml (data_sizes.xml) que enumera todos los valores de spinner.

    2 4 8 16 32   

En archivo main.xml: elemento Spinner

  

Luego en mi código de Java, agregué:

En mi actividad: Declaración

 Spinner spinnerSize; ArrayAdapter adapter; 

En una función vacía pública – initControls (): Definición

 spinnerSize = (Spinner)findViewById(R.id.spinnerSize); adapter = ArrayAdapter.createFromResource(this, R.array.chunks, android.R.layout.simple_spinner_item); adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); spinnerSize.setAdapter(adapter); spinnerSize.setOnItemSelectedListener(new MyOnItemSelectedListener()); 

Mi oyente spinner:

/ * Spinner Listener * /

 class MyOnItemSelectedListener implements OnItemSelectedListener { public void onItemSelected(AdapterView parent, View view, int pos, long id) { chunkSize = new Integer(parent.getItemAtPosition(pos).toString()).intValue(); } public void onNothingSelected(AdapterView parent) { // Dummy } } 

Usando un diseño de ruleta personalizado como este:

   

En la actividad:

  // populate the list ArrayList dataList = new ArrayList(); for (int i = 0; i < 4; i++) { dataList.add("Item"); } // set custom layout spinner_layout.xml and adapter Spinner spinnerObject = (Spinner) findViewById(R.id.spinnerObject); ArrayAdapter dataAdapter = new ArrayAdapter(this, R.drawable.spinner_layout, dataList); dataAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); spinnerObject.setAdapter(dataAdapter); spinnerObject.setOnTouchListener(new View.OnTouchListener() { public boolean onTouch(View v, MotionEvent event) { // to set value of first selection, because setOnItemSelectedListener will not dispatch if the user selects first element TextView spinnerTarget = (TextView)v.findViewById(R.id.spinnerTarget); spinnerTarget.setText(spinnerObject.getSelectedItem().toString()); return false; } }); spinnerObject.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { private boolean selectionControl = true; public void onItemSelected(AdapterView parent, View view, int pos, long id) { // just the first time if(selectionControl){ // find TextView in layout TextView spinnerTarget = (TextView)parent.findViewById(R.id.spinnerTarget); // set spinner text empty spinnerTarget.setText(""); selectionControl = false; } else{ // select object } } public void onNothingSelected(AdapterView parent) { } }); 

Combina esto:

 private long previousItemId = 0; @Override public long getItemId(int position) { long nextItemId = random.nextInt(Integer.MAX_VALUE); while(previousItemId == nextItemId) { nextItemId = random.nextInt(Integer.MAX_VALUE); } previousItemId = nextItemId; return nextItemId; } 

Con esta respuesta :

 public class SpinnerInteractionListener implements AdapterView.OnItemSelectedListener, View.OnTouchListener { private AdapterView.OnItemSelectedListener onItemSelectedListener; public SpinnerInteractionListener(AdapterView.OnItemSelectedListener selectedListener) { this.onItemSelectedListener = selectedListener; } boolean userSelect = false; @Override public boolean onTouch(View v, MotionEvent event) { userSelect = true; return false; } @Override public void onItemSelected(AdapterView parent, View view, int pos, long id) { if(userSelect) { onItemSelectedListener.onItemSelected(parent, view, pos, id); userSelect = false; } } @Override public void onNothingSelected(AdapterView parent) { if(userSelect) { onItemSelectedListener.onNothingSelected(parent); userSelect = false; } } } 

puede poner la primera celda de su matriz para que esté vacía ({“”, “some”, “some”, …}) y no haga nada si la posición es 0;

 public void onItemSelected(AdapterView parent, View view, int position, long id) { if(position>0) { label.setText(MainActivity.questions[position - 1]); } } 
  • si llena el conjunto por archivo xml, puede dejar el primer elemento vacío

Mi solución, en caso de que tengas un TextView como cada fila del spinner:

  // TODO: add a fake item as the last one of "items" final ArrayAdapter adapter=new ArrayAdapter(..,..,items) { @Override public View getDropDownView(final int position,final View convertView,final ViewGroup parent) { final View dropDownView=super.getDropDownView(position,convertView,parent); ((TextView)dropDownView.findViewById(android.R.id.text1)).setHeight(position==getCount()-1?0:getDimensionFromAttribute(..,R.attr.dropdownListPreferredItemHeight)); dropDownView.getLayoutParams().height=position==getCount()-1?0:LayoutParams.MATCH_PARENT; return dropDownView; } } ... spinner.setAdapter(adapter); _actionModeSpinnerView.setSelection(dataAdapter.getCount()-1,false); public static int getDimensionFromAttribute(final Context context,final int attr) { final TypedValue typedValue=new TypedValue(); if(context.getTheme().resolveAttribute(attr,typedValue,true)) return TypedValue.complexToDimensionPixelSize(typedValue.data,context.getResources().getDisplayMetrics()); return 0; } 

Base en la respuesta de @Jonik He creado una extensión completamente funcional para ArrayAdapter

 class SpinnerArrayAdapter : ArrayAdapter { private val selectText : String private val resource: Int private val fieldId : Int private val inflater : LayoutInflater constructor(context: Context?, resource: Int, objects: Array, selectText : String? = null) : super(context, resource, objects) { this.selectText = selectText ?: context?.getString(R.string.spinner_default_select_text) ?: "" this.resource = resource this.fieldId = 0 this.inflater = LayoutInflater.from(context) } constructor(context: Context?, resource : Int, objects: List, selectText : String? = null) : super(context, resource, objects) { this.selectText = selectText ?: context?.getString(R.string.spinner_default_select_text) ?: "" this.resource = resource this.fieldId = 0 this.inflater = LayoutInflater.from(context) } constructor(context: Context?, resource: Int, textViewResourceId: Int, objects: Array, selectText : String? = null) : super(context, resource, textViewResourceId, objects) { this.selectText = selectText ?: context?.getString(R.string.spinner_default_select_text) ?: "" this.resource = resource this.fieldId = textViewResourceId this.inflater = LayoutInflater.from(context) } constructor(context: Context?, resource : Int, textViewResourceId: Int, objects: List, selectText : String? = null) : super(context, resource, textViewResourceId, objects) { this.selectText = selectText ?: context?.getString(R.string.spinner_default_select_text) ?: "" this.resource = resource this.fieldId = textViewResourceId this.inflater = LayoutInflater.from(context) } override fun getDropDownView(position: Int, convertView: View?, parent: ViewGroup?): View { if(position == 0) { return initialSelection(true) } return createViewFromResource(inflater, position -1, convertView, parent, resource) } override fun getView(position: Int, convertView: View?, parent: ViewGroup?): View { if(position == 0) { return initialSelection(false) } return createViewFromResource(inflater, position -1, convertView, parent, resource) } override fun getCount(): Int { return super.getCount() + 1 // adjust for initial selection } private fun initialSelection(inDropDown: Boolean) : View { // Just simple TextView as initial selection. val view = TextView(context) view.setText(selectText) view.setPadding(8, 0, 8, 0) if(inDropDown) { // Hide when dropdown is open view.height = 0 } return view } private fun createViewFromResource(inflater: LayoutInflater, position: Int, @Nullable convertView: View?, parent: ViewGroup?, resource: Int): View { val view: View val text: TextView? if (convertView == null || (convertView is TextView)) { view = inflater.inflate(resource, parent, false) } else { view = convertView } try { if (fieldId === 0) { // If no custom field is assigned, assume the whole resource is a TextView text = view as TextView } else { // Otherwise, find the TextView field within the layout text = view.findViewById(fieldId) if (text == null) { throw RuntimeException("Failed to find view with ID " + context.getResources().getResourceName(fieldId) + " in item layout") } } } catch (e: ClassCastException) { Log.e("ArrayAdapter", "You must supply a resource ID for a TextView") throw IllegalStateException( "ArrayAdapter requires the resource ID to be a TextView", e) } val item = getItem(position) if (item is CharSequence) { text.text = item } else { text.text = item!!.toString() } return view }