views:

617

answers:

3

What I'd like to do is change the state (really, the background) of an EditText to reflect validity of its contents. E.g. if the user enters 999 where 999 is contextually invalid, the EditText should have a red border in place of the default orange border, likewise once the text is valid it should have a green border.

Methods I've explored:

  1. Changing the style of the EditText programmatically via something like editor.setStyle(R.styles.SomeID). Seems to be impossible within android.
  2. Adding custom states (state_valid, state_invalid) in R.attr, associating them with red/ green 9-patches, then calling drawable.setState() with one of these states. This worked in the sense that the state could be read back via getState(), but the border did not change colour.
  3. Setting the background resource directly upon detection of (in)validity. This works ok, causing the correct visual effect, but seems a little hokey, and allows only one state (e.g. I have to manually check for whether the EditText is pressed, enabled etc).

Given limited UI real-estate I am hesitant to introduce a separate UI element to visually feedback the text's validity to the user, hence my desire to display it in the EditText itself.

So.. is this something that's even feasible? It seems like a fairly common use case, so has anyone achieved what I'm trying to do in a straightforward and elegant manner?

+1  A: 

Well, I'd just extend the EditText class and build the desired functionality on top ( using the third approach you are suggesting, because it works :-) ). Doing this, you have to walk the way only once, and are open to change your implementation once you know the best way ( I would have personally solved it also using the third approach, seems fine to me ).

moritz
Thanks for the response. My issue with the third approach is that I have to do a deal of work to check for each state or combination, e.g. the EditText may be pressed-enabled-valid, or notpressed-enabled-invalid, and so on, causing my subclass to have to check for each possible combination in order to display the correct background. This seems clunky and inelegant, not to mention violating DRY.
Simon
+2  A: 

I would recommend changing the text color to indicate validity, rather than changing the color of the focus ring by any of the techniques you describe (of which only #3 seems practical).

Another possibility is to try setCompoundDrawablesWithIntrinsicBounds() to modify an icon on the left or right side of the EditText contents to indicate validity. I remember discussing this technique with somebody a few months back and forget if they got it working or not.

And, of course, another option is to not allow invalid input, via a custom input filter or listener or something.

CommonsWare
Thanks for your response.Changing the text color is an option of course, but leads to a less subtle effect IMO. Likewise, changing an icon to indicate (in)validity means the feedback does not occur at the point of any discrepancy, which is bad UI.Finally, applying a filter is not really an option here since the input may become valid with further characters, such as a partially-complete phone number.
Simon
"Likewise, changing an icon to indicate (in)validity means the feedback does not occur at the point of any discrepancy, which is bad UI." That is not what I wrote. My proposed solution (if you get it working) offers a superior UI IMHO -- instead of users having to guess that changing focus ring colors means changing validity, you can use a more visually potent icon right inside the EditText that you consider invalid.
CommonsWare
A: 

i think a call to invalidateDrawable(yourDrawable) would work with approach number 2. i didn't try .. but it make sense

kdehairy