How do you create the setError()
(similar to that of a TextView/EditText
) function for a Spinner
? The following doesn't work:
I tried extending the Spinner class and in the 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);
setError
method:
public void setError(String str) {
if (tv != null)
tv.setError(str);
if(tv2!=null)
tv2.setError(str);
if (ctv != null)
ctv.setError(str);
}
Similar to @Gábor's solution, but I didn't need to create my own adapter. I just call the following code in my validate function (i.e. on submit button clicked)
I guess that Spinner is not the right place to put this method. In case of Spinner you should select one value and to values in the Spinner should be filtered on the level of your adapter. Thus, a user can choose only those values that are in the Spinner.
You can create your own adapter (extends BaseAdapter implements SpinnerAdapter). That way, you can access the TextViews that are displayed in the spinner. (getView and createViewFromResource methods - example: ArrayAdapter) When you add an empty list item to allow the user to keep the field empty until it becomes mandatory (first item in the spinner), you can store it's TextView as a private member in the adapter. Then, when it comes time to call setError("...") from the Activity or Fragment, you can call it on the adapter who can pass it to the empty TextView.
Using a hidden TextView to get a pop-up message to appear
This solution involves adding an additional hidden textbox just below the spinner just at the right position to allow the TextView's error dialog to show, whilst also using the TextView set on the spinner's layout XML to allow the red (!) icon to be displayed. So in effect, two textviews are used -- one for the icon, and another (hidden) one to allow the error dialog.
This is what it looks like when not in an error state (use
SetError(null)
):This is what it looks like when there is an error (use
SetError("my error text, ideally from a resource!")
):Here is the excerpt of the spinner's layout XML. There is a RelativeLayout used to ensure that the TextView is as close as possible to the spinner, and has just enough paddingRight to ensure that the arrow on the message dialog is aligned just under the red error (!) icon. The hidden (fake) TextView is positioned relative to the Spinner.
Note:
@drawable/selector_listview
defined outside the scope of this solution. See example here of how to get this to work, as it's off topic for this answer.Here is the code to make it work. Just call the
SetError(errMsg)
either withnull
to clear the error, or with text to set it in an error state.In the
SetError
function above, example there is some additional code that causes the text in the Spinner to shake when the error is set. This is not required to make the solution work, but is a nice addition. See here for the inspiration for this approach.Kudos to @Gábor for his solution which makes use of the TextView on the Spinner's item layout XML. The code
View view = spnMySpinner.getSelectedView();
(based on @Gábor's solution) is necessary, because it gets the currently displayed TextView, rather than using afindViewById
, which would just get the first TextView in the list (based on the Resource ID provided), and hence would not work (to display the red (!) icon) if very first item in the list is not selected.I would suggest you to put an empty
EditText
right behind your spinner.On the xml set that
EditText
Now when you want to set an error to your spinner, simply set that error to the
EditText
.Remember not to set that
EditText
toinvisibille
/gone
. It won't work that way.Also, note that by this method you can decide exactly where you want your error to appear.
Thanks Gabor for your fantastic solution. In furtherance to your point, my solution is thus:
Custom Adapter
Use adapter for Spinner
Check for validation