Creación de un setError () para el Spinner

¿Cómo se crea la función setError() (similar a la de un TextView/EditText ) para un Spinner ? Lo siguiente no funciona:

He intentado ampliar la clase Spinner y en el constructor:

 ArrayAdapter<String> aa = new ArrayAdapter<String>(getContext(), android.R.layout.simple_spinner_item, android.R.id.text1, items); aa.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); setAdapter(aa); tv = (TextView) findViewById(android.R.id.text1); // types_layout_list_tv ctv = (CheckedTextView) aa.getDropDownView(1, null, null); tv2 = (TextView) aa.getView(1, null, null); 

Método setError :

  public void setError(String str) { if (tv != null) tv.setError(str); if(tv2!=null) tv2.setError(str); if (ctv != null) ctv.setError(str); } 

Similar a la solución de @ Gábor, pero no necesité crear mi propio adaptador. Acabo de llamar el código siguiente en mi función de validación (es decir, en el botón de envío pulsado)

  TextView errorText = (TextView)mySpinner.getSelectedView(); errorText.setError("anything here, just to add the icon"); errorText.setTextColor(Color.RED);//just to highlight that this is an error errorText.setText("my actual error text");//changes the selected item text to this 

Tengo una solución que no implica la creación de un campo de edición adicional, pero usted necesita su propio SpinnerAdapter , como de costumbre.

Asegúrese de que tiene al menos un TextView en el diseño que utiliza en su adaptador getView() (normalmente tiene que, de todos modos).

Agregue la siguiente función a su adaptador (cambie el name al ID de su TextView ):

 public void setError(View v, CharSequence s) { TextView name = (TextView) v.findViewById(R.id.name); name.setError(s); } 

Llame a la setError() de su código de esta manera:

 YourAdapter adapter = (YourAdapter)spinner.getAdapter(); View view = spinner.getSelectedView(); adapter.setError(view, getActivity().getString(R.string.error_message)); 

Básicamente, como con cualquier otro control, sólo que usted lo llama en su adaptador y usted tiene que proporcionar la vista también.

Esto mostrará el icono de error en la hiladora como es el caso con otros controles.

Utilizar un TextView oculto para que aparezca un mensaje emergente

Esta solución implica agregar un cuadro de texto oculto adicional justo debajo de la ruleta justo en la posición correcta para permitir que se muestre el diálogo de error de TextView, mientras que también se utiliza el conjunto TextView en la disposición XML del rotador para permitir que se muestre el icono rojo (! Por lo tanto, en efecto, dos vistas de texto se utilizan – una para el icono, y otra (oculta) para permitir el diálogo de error.

Esto es lo que parece cuando no está en un estado de error (use SetError(null) ):

Spinner en estado válido

Esto es lo que parece cuando hay un error (use SetError("my error text, ideally from a resource!") ):

Spinner en estado no válido

Aquí está el extracto del XML de la disposición del hilandero. Hay un RelativeLayout usado para asegurar que el TextView esté tan cerca como sea posible del spinner, y tiene suficiente paddingRight para asegurarse de que la flecha en el cuadro de diálogo de mensaje esté alineada justo debajo del icono de error rojo (!). El TextView ocultado (falso) se posiciona en relación con el Spinner.

  <RelativeLayout android:layout_width="wrap_content" android:layout_height="wrap_content" android:gravity="top|left" > <Spinner android:id="@+id/spnMySpinner" android:layout_width="400dp" android:layout_height="wrap_content" android:layout_alignParentTop="true" android:dropDownSelector="@drawable/selector_listview" android:background="@android:drawable/btn_dropdown" android:paddingBottom="0dp" android:layout_marginBottom="0dp" /> <!-- Fake TextView to use to set in an error state to allow an error to be shown for the TextView --> <android.widget.TextView android:id="@+id/tvInvisibleError" android:layout_width="0dp" android:layout_height="0dp" android:layout_alignRight="@+id/spnMySpinner" android:layout_alignBottom="@+id/spnMySpinner" android:layout_marginTop="0dp" android:paddingTop="0dp" android:paddingRight="50dp" android:focusable="true" android:focusableInTouchMode="true" /> </RelativeLayout> 

Nota: @drawable/selector_listview definido fuera del alcance de esta solución. Vea el ejemplo aquí de cómo conseguir que esto funcione, ya que está fuera de tema para esta respuesta.

Aquí está el código para que funcione. Simplemente llame a SetError(errMsg) con null para borrar el error, o con texto para establecerlo en un estado de error.

 /** * When a <code>errorMessage</code> is specified, pops up an error window with the message * text, and creates an error icon in the secondary unit spinner. Error cleared through passing * in a null string. * @param errorMessage Error message to display, or null to clear. */ public void SetError(String errorMessage) { View view = spnMySpinner.getSelectedView(); // Set TextView in Secondary Unit spinner to be in error so that red (!) icon // appears, and then shake control if in error TextView tvListItem = (TextView)view; // Set fake TextView to be in error so that the error message appears TextView tvInvisibleError = (TextView)findViewById(R.id.tvInvisibleError); // Shake and set error if in error state, otherwise clear error if(errorMessage != null) { tvListItem.setError(errorMessage); tvListItem.requestFocus(); // Shake the spinner to highlight that current selection // is invalid -- SEE COMMENT BELOW Animation shake = AnimationUtils.loadAnimation(this, R.anim.shake); spnMySpinner.startAnimation(shake); tvInvisibleError.requestFocus(); tvInvisibleError.setError(errorMessage); } else { tvListItem.setError(null); tvInvisibleError.setError(null); } } 

En la función SetError anterior, ejemplo hay algún código adicional que hace que el texto en el Spinner agite cuando se establece el error. Esto no es necesario para que la solución funcione, pero es una buena adición. Vea aquí la inspiración para este enfoque.

Felicitaciones a @ Gábor por su solución que hace uso de TextView en la disposición XML del elemento Spinner. El código View view = spnMySpinner.getSelectedView(); (Basado en la solución de @ Gábor), ya que obtiene el TextView mostrado actualmente, en lugar de usar un findViewById , que sólo obtendría el primer TextView en la lista (basado en el ID de recurso proporcionado) y, por tanto, no funcionaría Mostrar el icono rojo (!)) Si el primer elemento de la lista no está seleccionado.

Le sugeriría que pusiera un derecho vacío de EditText detrás de su hilandero.

En el conjunto xml que EditText

 android:enabled="false" android:inputType="none" 

Ahora, cuando desea establecer un error en su hiladora, simplemente establezca ese error en el EditText .

Recuerde no establecer que EditText para invisibille / gone . No funcionará de esa manera.

Además, tenga en cuenta que mediante este método puede decidir exactamente dónde desea que aparezca su error.

Esto puede hacerse sin utilizar un diseño o adaptador personalizado.

 ((TextView)spinner.getChildAt(0)).setError("Message"); 

El único inconveniente de este enfoque es que el pequeño popup con el texto de error no se mostrará cuando se pulsa el icono.

Gracias Gabor por su fantástica solución. En consecuencia a su punto, mi solución es así:

Adaptador personalizado

  public class RequiredSpinnerAdapter<T> extends ArrayAdapter<T> { public RequiredSpinnerAdapter(Context context, int textViewResourceId, java.util.List<T> objects) { super(context, textViewResourceId, objects); } int textViewId = 0; @Override public View getView(int position, View convertView, ViewGroup parent) { View view = super.getView(position, convertView, parent); if (view instanceof TextView) { textViewId = view.getId(); } return view; } public View getDropDownView(int position, View convertView, ViewGroup parent) { View row = super.getView(position, convertView, parent); return (row); } public void setError(View v, CharSequence s) { if(textViewId != 0){ TextView name = (TextView) v.findViewById(textViewId); name.setError(s); } } } 

Utilice el adaptador para Spinner

 ArrayAdapter<String> arrayAdapter = new RequiredSpinnerAdapter<String>(PropertyAdd.this, R.layout.checked, status_arr); marketstatus_spinner.setAdapter(arrayAdapter); marketstatus_spinner.setOnItemSelectedListener(new OnItemSelectedListener() { @Override public void onItemSelected(AdapterView<?> arg0, View arg1, int arg2, long arg3) { // Put code here } @Override public void onNothingSelected(AdapterView<?> arg0) { // Put code here } }); 

Verificar la validación

 private boolean checkValidation() { if(marketstatus_spinner.getSelectedItem().toString().equals("")){ RequiredSpinnerAdapter adapter = (RequiredSpinnerAdapter)marketstatus_spinner.getAdapter(); View view = marketstatus_spinner.getSelectedView(); adapter.setError(view, "Please select a value"); return false; } } 

Supongo que Spinner no es el lugar adecuado para poner este método. En el caso de Spinner debe seleccionar un valor y los valores en el Spinner deben filtrarse en el nivel de su adaptador. Por lo tanto, un usuario puede elegir sólo aquellos valores que están en el Spinner.

Puede crear su propio adaptador (extiende BaseAdapter implementa SpinnerAdapter). De esta forma, puede acceder a las TextView que se muestran en la hiladora. (Métodos getView y createViewFromResource – example: ArrayAdapter ) Cuando agrega un elemento de lista vacía para permitir que el usuario mantenga el campo vacío hasta que se convierta en obligatorio (primer elemento en el hilandero), puede almacenar TextView como un miembro privado en el adaptador . A continuación, cuando llegue el momento de llamar a setError ("…") de la Actividad o Fragmento, puede llamar al adaptador que pueda pasarlo al TextView vacío.

 @Override public View getView(int position, View convertView, ViewGroup parent) { return createViewFromResource(position, convertView, parent, mTextViewId); } private View createViewFromResource(int position, View convertView, ViewGroup parent, int resource) { View view; TextView text; if (convertView == null) { view = inflater.inflate(resource, parent, false); } else { view = convertView; } try { text = (TextView) view; } catch (ClassCastException e) { Log.e(TAG, "You must supply a resource ID for a TextView", e); throw new IllegalStateException("MyAdapter requires the resource ID to be a TextView", e); } MyItem i = getItem(position); String s = (null != i) ? i.toString() : ""; text.setText(s); if ("".equals(s) && null == mEmptyText) { this.mEmptyText = text; } return view; } public void setError(String errorMessage) { if (null != mEmptyText) { mEmptyText.setError(errorMessage); } else { Log.d(TAG, "mEmptyText is null"); } } 

En realidad esto es muy importante, solo necesitas tener un solo TextView en tu vista y luego obtener la vista seleccionada desde tu hilandero usando getSelectedView() si la vista principal en tu vista seleccionada es TextView luego Cast directamente tu vista a TextView y setError Me gusta esto :

 ((TextView) jobCategory.getSelectedView()).setError("Field Required"); 

Else si la vista de texto no es directamente la vista PRINCIPAL entonces usted necesita encontrarla por la identificación y la echa otra vez y setError esta manera:

  ((TextView) jobCategory.getSelectedView().findViewById(R.id.firstName)).setError("Field Required"); 
  • Implementación de eventos Spinner with Butter Knife
  • Agregar OnItemSelectedListener a Spinner
  • Cómo establecer un texto predeterminado en un Spinner
  • Android - ¿Cómo puedo cambiar un valor de spinner sin activar setOnItemSelectedListener
  • Spinner dropdown dibujo de la parte superior de la pantalla en listview después de seleccionar el elemento
  • Android: Cómo obtener el ID del elemento seleccionado de Spinner
  • ¿Cómo crear un spinner con título en él?
  • ¿Cómo puedo agregar elementos a una ruleta en Android?
  • Establecer el elemento seleccionado de la hiladora mediante programación
  • Tema predeterminado de Spinner a EditarTexto android
  • Spinner que agrega la matriz de la secuencia en la selección del artículo cómo puede conseguir el valor relacionado artículo en androide
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.