69

I have a view with radios, inputs and a button and when I click it, I want to check that all inputs contain information. How can I iterate through the view's elements in the activity and check if every textview meets the aforementioned requirement ? Thanks.

xain
  • 13,159
  • 17
  • 75
  • 119

4 Answers4

136

I've done something similar in some code I don't have with me at the moment, but from memory it should be something like this (assuming a parent view LinearLayout with an id of "layout"):

LinearLayout layout = (LinearLayout)findViewById(R.id.layout);
boolean success = formIsValid(layout);

public boolean formIsValid(LinearLayout layout) {
    for (int i = 0; i < layout.getChildCount(); i++) {
        View v = layout.getChildAt(i);
        if (v instanceof EditText) {
            //validate your EditText here
        } else if (v instanceof RadioButton) {
            //validate RadioButton
        } //etc. If it fails anywhere, just return false.
    }
    return true;
}
Kevin Coppock
  • 133,643
  • 45
  • 263
  • 274
  • I like your use of getClass. I guess in a table or similar container type views one could use a recursive call to pick up those inner children as well, right? – Lumis Jan 26 '11 at 22:21
  • 1
    Good question! I would think so. I suppose you could make the formIsValid function take a generic View parameter, and cast, so that you could do something like `if (c == TableLayout.class) if (!formIsValid(v)) return false;`. You'd have to make sure not to just return true after the nested layout to avoid dropping out before finishing the rest of the original form. – Kevin Coppock Jan 26 '11 at 22:26
  • That's precisely my case, getChildAt() returns tablerows only. – xain Jan 27 '11 at 13:50
  • I'm assuming since you marked this accepted that it worked for you? In case I'm wrong, you should also be able to do the same recursion for `TableRow.class`, and check the children there as well. – Kevin Coppock Jan 27 '11 at 14:15
  • 2
    if (v instanceof EditText) { } is neater than comparing class definitions – S-K' Mar 27 '14 at 11:41
  • Works like wonder!! Thanks.@kcoppock please, do you think you could help me with this question http://stackoverflow.com/questions/25598696/recommended-way-order-to-read-data-from-a-webservice-parse-that-data-and-inse – Axel Sep 01 '14 at 22:57
  • * `instanceof` tests whether the object reference on the left-hand side (LHS) is an instance of the type on the right-hand side (RHS) or some subtype. * `getClass() == ..`. tests whether the types are identical. –  Apr 06 '18 at 03:04
25

To apply the method by kcoppock recursively, you can change it to this:

private void loopViews(ViewGroup view) {
    for (int i = 0; i < view.getChildCount(); i++) {
        View v = view.getChildAt(i);

        if (v instanceof EditText) {
            // Do something

        } else if (v instanceof ViewGroup) {

            this.loopViews((ViewGroup) v);
        }
    }
} 
Tunaki
  • 132,869
  • 46
  • 340
  • 423
Kalimah
  • 11,217
  • 11
  • 43
  • 80
10

If you are writing in Kotlin, Android Jetpack's Kotlin extensions (KTX) provide extension functions for iterating over a ViewGroup's children.

myViewGroup.forEach { ... }

myViewGroup.forEachIndexed { index, view -> ... }

Just add the dependency to your app. Check the link above to get the most up-to-date version.

implementation "androidx.core:core-ktx:1.2.0"

These extensions contains hoards of useful functions otherwise chalked up as boilerplate. Worth checking out now to save time in the future!

M. Palsich
  • 1,748
  • 13
  • 18
0

Your onClickListener supplies the View v object; use View rV = v.getRootView() to position yourself on the form. Then use rV.findViewWithTag( ... ) or rV.findViewByID(R.id. ... ) to locate your form elements.

naXa stands with Ukraine
  • 35,493
  • 19
  • 190
  • 259
gssi
  • 5,043
  • 5
  • 23
  • 23
  • 1
    Thanks for your reply, but there's got to be a more "general" way. Something like "iterate through all the view's elements that are of type TextView". – xain Jan 26 '11 at 21:21