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:
- ¿Cómo se puede utilizar un marcador de posición de carga que es un spinner animado con cargadores de imágenes como Glide, Picasso etc?
- Crear un hilandero por programación android
- Android - Cómo mostrar un spinner con valor pero mostrar otro diferente
- Actualizar City Spinner con notifyDataSetChanged después de seleccionar estado
- Cómo hacer una fecha spinner en Android
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); }
- ¿Cómo puedo administrar la altura de los ítems de spinner android?
- ICS Spinner ("desplegable" en lugar de diálogo) en versiones anteriores de Android
- Android Spinner Dropdown flecha que no se muestra
- Cómo deshabilitar onItemSelectedListener que se invocará al configurar el elemento seleccionado por código
- Androide spinner evento de incendio cuando la misma selección de artículo se hace
- Cómo cambiar el color del texto del hilandero
- Cómo usar spinner
- Mostrar hilandero en AlertDialog
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)
):
Esto es lo que parece cuando hay un error (use SetError("my error text, ideally from a resource!")
):
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");
- Cómo hacer que el texto de edición no se edita pero se puede hacer clic en JAVA
- Cómo establecer state_selected en ripple drawable