6

Searched and working on this a long while - no luck. ( It must be simple ? Thanks for the assist. )

Trying to get / set a screen full of EditTexts' text, but not with the usual, more hard-coded way:

... findViewById (R.id.SomeTextWidgetId) ;

Instead, I'm trying to figure out a reusable way via a variable holding the (String) name_of_widget.

In psuedo code:

findViewById (R.id.>> StringVarHere << ); // how to do that ?

I tried also this findViewById method, but it didn't work (!?)

//// given:

static final String FIELD_TV_FEE   = "TextViewFee" ;
static final String FIELD_TV_FOO   = "TextViewFoo" ;
static final String FIELD_TV_FUM   = "TextViewFum" ;
//// and some arbitrary number more of similar fields  

static final String [] ALL_FIELDS = {

    FIELD_TV_FEE ,
    FIELD_TV_FOO ,  
    FIELD_TV_FUM   // ...
 } ; 

//// ...

    //// this part works
    int ResourceID;
    String stringVarHere = FIELD_TV_FEE; 

    //// outputs a correct id, say '0x7f05000f' as in R.id.xxx below
    ResourceID = context
                       .getResources()
                       .getIdentifier ( stringVarHere,
                                        "id", 
                                        context 
                                          .getApplicationInfo()
                                          .packageName
                                      ) ;
    Log.d ("MyClass" , "RESID = " + Integer.toHexString(ResourceID) ) ;  
/*
 * that's where I'm stuck ^^^ ... how do I do:
 */

String field_name ;

for ( field_name : ALL_FIELDS ) {
    (EditText) SomethingLike_a_findViewById(field_name).setText ("Hello Wurld") ;
}

I've tried .setId ...

//// details

    <!-- excerpt from working xml layout -->
    <EditText
        android:id="@+id/TextViewFee"
        android:inputType="text"
        android:layout ... etc ...         
        />
    <EditText
        android:id="@+id/TextViewFoo"
        android:inputType="text"
        android:layout ... etc ...         
        />
    <EditText
        android:id="@+id/TextViewFum"
        android:inputType="text"
        android:layout ... etc ...         
        />

As expected, the gen'ed R file has something like this:

// ...
public static final class id {
    public static final int TextViewFee=0x7f05000f;
    public static final int TextViewFum=0x7f05001c;
    public static final int TextViewFoo=0x7f05001d;
    // ... etc

Yes, thanks - it makes sense to do it in the activity. I was trying to keep it from getting too code bulky. Here's what I'm doing now, based on your and A-C's helpful suggestions. The intention is to get all the text of fields of a form back in one String[]. (I know I could brute force all the fields too.)

What do you all think about this below - seems very similar to your suggestion, madlymad ? I am wondering if this is a poor design approach ?

public class FoodBar {

private Activity activity; 
private Context ctx;

public  FoodBar ( Activity _activity ) {        
    this.activity = _activity;
    this.ctx = this.activity.getApplicationContext() ;
}

public String[] getTextFromAllEditTexts () { // the UI views

    int res_id = 0;
    int i = 0;   

    String [] retValues = new String [MyClassName.ALL_FIELDS_LENGTH] ;

    for (String field : MyClassName.ALL_FIELDS_ALL_VEHICLES) {

       res_id = this.ctx.getResources()
                        .getIdentifier ( field, "id", this.ctx.getPackageName() );

           ((EditText) this.activity
                           .findViewById (res_id))
                           .setText( "Meat and Potatoes" ) ;

               // redundant - get it right back to make sure it really went in !  
        retVal[i++] = ((EditText) this.activity
                                        .findViewById (res_id))
                                        .getText().toString() ;
    }

     return retVal;

} // end func
} // end class

Then from the Activity class, it's just:

String [] theFields = null;
FoodBar = new FoodBar (this);

try {

     theFields = FoodBar.getTextFromAllEditTexts ();

} catch (Exception e) {
     Log.d ("OOPS", "There's a big mess in the Foodbar: " + e.toString() );
}
Community
  • 1
  • 1
Howard Pautz
  • 415
  • 7
  • 21
  • Looking at the SO answer you say you tried, it should work. Just make sure to do all this after you've called `setContentView()` – A--C Mar 02 '13 at 22:06
  • Sorry, "SO" ? what's that ? ... yup, forgetting to setContentView means there's no xml for it to refer to :) ... – Howard Pautz Mar 02 '13 at 22:20
  • SO = "StackOverflow". I think you should post the trial you had using either mine or that answer's implementation. I've tried my implementation and it did work, so I'm unsure why it's not working for you. – A--C Mar 02 '13 at 22:23
  • 1
    Thanks for your time on this A-C ... your 10.5 k replies shows how helpful you've been ! ... well, if it's working for you, then I must have some other glitch in it ... back to adding in more Log.d 's :)) till I figure it out. – Howard Pautz Mar 02 '13 at 22:40

3 Answers3

3

The way you could do it is (as I understand the way you are trying):

This can be in non-Activity (YourClassname.java):

public static int getMyId(Context context, String field) {
     return context.getResources().getIdentifier (field, "id", context.getPackageName());
}

in Activity-class:

for ( String field_name : YourClassname.ALL_FIELDS ) {
    int resid = YourClassname.getMyId(context, field_name);
    if(resid != 0) { // 0 = not found 
       EditText et = (EditText) findViewById(resid);
       if (et != null) {
          et .setText ("Hello Wurld") ;
       }
    }
}

But I think it's better to code in the activity class like:

String packageName = getPackageName();
Resources res = getResources();
for ( String field_name : YourClassname.ALL_FIELDS ) {
    int resid = res.getIdentifier (field_name, "id", packageName);
    if(resid != 0) {// 0 = not found 
       EditText et = (EditText) findViewById(resid);
       if (et != null) {
          et .setText ("Hello Wurld") ;
       }
    }
}
madlymad
  • 6,367
  • 6
  • 37
  • 68
2

A-C suggested something along the lines of:

res_id = getResources().getIdentifier (field, "id", getPackageName());
((EditText)findViewById (res_id)).setText("NoLongerFubar");

this DOES work - when I tried it standalone in a test rig. Thanks ! Still not sure what was blowing up, but I suspect it was Context or Resource items not being accessible.

Howard Pautz
  • 415
  • 7
  • 21
  • If not on Activity class use `context.getResources().getIdentifier (field, "id", getPackageName());` – madlymad Mar 02 '13 at 23:26
  • Thanks madlymad - that's exactly what I had in my OP ! and the context was good (AFAICT ?) had passed context into the non-activity classes constructor - and context.getResources().getIdentifier ... was returning a valid id, but when I tried to use it, got a null pntr exception. ... – Howard Pautz Mar 02 '13 at 23:38
  • See reply above - (Aside to Kev - thanks for fixing the mis-post !) – Howard Pautz Mar 03 '13 at 01:13
1

Note that variable names (such as R.id.some_id) are only available at compile time and cannot be accessed from a String value at run time. Since these ids are declared as ints, you might consider using an int[] or List<Integer> to store the ids. Depending on how dynamic your layout is and what you are doing with the Views in it, you might even want to simply create the Views at run time and store an array or List of them without using any ids at all.

Code-Apprentice
  • 81,660
  • 23
  • 145
  • 268
  • 1
    thanks for the List suggestion - a good idea ... the trouble wasn't so much with getting/saving the Ids as much as it was using them due to context not being in place. – Kev moved my reply to the correct place too above. – Howard Pautz Mar 03 '13 at 01:15
  • @HowardPautz Glad you figured it out. Good luck with your Android programming! And welcome to SO. – Code-Apprentice Mar 03 '13 at 01:18
  • Code-Guru, thanks so much on the luck and the welcome! Very much appreciated as SO is nothing less than *amazing* ... virtually every Google search on a bug, no matter how obscure, finds SO on the top of the hits! – Howard Pautz Mar 03 '13 at 01:27
  • @HowardPautz Did you get my chat ping? (Check the upper-left corner of any SO page.) For some reason the chat site still says you only have 1 rep, so I can't invite you directly ;-( – Code-Apprentice Mar 03 '13 at 01:33
  • '@'Code-Guru - not sure ... and do we have to have more rep points to put a '@' in front of a name?? My rep just bumped from 1 to 26 today :)) ... maybe it needs 24 hours to settle, or for me to become validated LOL. (further tangent -via you I've just learned about the SO Math site - how cool!) – Howard Pautz Mar 03 '13 at 01:39
  • @HowardPautz Nope, you don't need any rep to @ someone in comments. I believe you need 20 rep to chat. I suspect that when I tried to invite you to chat, your new rep hadn't been updated on the chat side of the website. – Code-Apprentice Mar 05 '13 at 01:34
  • |<-- that's odd, when I type "@Code-Guru" on line 1, pos1, then add the comment, it trims off the entire "@Code-Guru" as you see here. – Howard Pautz Mar 05 '13 at 03:19
  • @HowardPautz When you post a comment to my answer, I get notified automagically without the @, so it is unnecessary. – Code-Apprentice Mar 05 '13 at 03:22
  • understood - what I don't get is precisely HOW you get (or are allowed ?) to put the "@" in front of the name! When I try "@Hello" at the start of the line, it just removes it! – Howard Pautz Mar 05 '13 at 04:12
  • See http://stackoverflow.com/privileges/comment. "You can only @reply to users who have already left a comment, or edited the post." Also http://meta.stackexchange.com/questions/43019/how-do-comment-replies-work has a good tutorial about @. – Code-Apprentice Mar 06 '13 at 03:31
  • '@' Code-Guru - thanks for the links. More precisely perhaps would be 'you can only @reply to users who have left a comment about, or edited, the *original* post/question.' I can '@' you up above in my OP in the comment section, but not right here, as this is *your* post... (So Now I understand the automagically part you mention here :)) ... but I find it annoyingly un-normalized to not be able to do it here (even though it would be redundant LOL ) – Howard Pautz Mar 06 '13 at 19:34
  • @HowardPautz I was quoting from the first link. I'm pretty sure you can @ me from someone else's answer as well. – Code-Apprentice Mar 07 '13 at 00:57