9

I want to be able to iterate through all of the fields in the generated R file.

Something like:

for(int id : R.id.getAllFields()){
//Do something with id, like create a view for each image
}

I've tried reflection, but I can't seem to load a specific inner class that's contained inside the R class. So, for example, this wouldn't work for me:

Class c = Class.forName("packageName.R.id")

I can reflect on the R class itself, but I need the fields within the id class.

I also tried looking through the Resources class, but couldn't find anything there. In that case, it seems you can take a resourceID and get the string name of that id, or take a string name and get the corresponding resourceID. I couldn't find anything like:

int[] Resources.getAllResourceIDs()

Maybe I'm going about this wrong. Or maybe I shouldn't fight typing them all in by hand, e.g.:

int[] myIds = {R.id.firstResource, R.id.secondResource}

This approach has the downside of not being as flexible when working with my UI designer. Whenever he adds a new resource to the XML file, I'll have to update the code. Obviously not too painful, but it would still be nice to have and it seems like it should be doable.

EDIT:

The answer below about ViewGroup.getChildCount()/ViewGroup.getChildAt() works fine. But, I also had to find a way to instantiate my XML ViewGroup/Layout. To do that, try something like:

LayoutInflater li = MyActivity.getLayoutInflater();
ViewGroup vg = (ViewGroup) li.inflate(R.layout.main, null);
Cœur
  • 37,241
  • 25
  • 195
  • 267
John Tabs
  • 363
  • 1
  • 3
  • 10
  • I'm not saying this to be snarky but IMHO the fact that you feel you need to ask this question means you're probably doing something wrong. Can you elaborate on your use case for doing this. I just can't think of any reason why I'd want access to all the id's defined throughout my entire application. – Rich Schuler Aug 23 '10 at 06:45
  • 1
    I don't want access all of the id's, but rather, all of the resource id's under a certain name (e.g. R.imageViewIds). This way, in my code, I can add an event listener or whatever to each of them in one for loop. My UI will have multiple ImageViews that will all respond to events, and it would be nice if I could access all of those ImageViews without hand-coding each by name (e.g. IView1.setListener(myListener); IView2.setListener(myListener);) Also, then I won't have to refactor my code if my UI designer decides to rename things in the XML file. – John Tabs Aug 23 '10 at 06:57

3 Answers3

7

I found that "Class.forName(getPackageName()+".R$string");" can give you access to the string resources and should work for id, drawable, exc as well.

I then use the class found like this:


import java.lang.reflect.Field;

import android.util.Log;

public class ResourceUtil {

    /**
     * Finds the resource ID for the current application's resources.
     * @param Rclass Resource class to find resource in. 
     * Example: R.string.class, R.layout.class, R.drawable.class
     * @param name Name of the resource to search for.
     * @return The id of the resource or -1 if not found.
     */
    public static int getResourceByName(Class<?> Rclass, String name) {
        int id = -1;
        try {
            if (Rclass != null) {
                final Field field = Rclass.getField(name);
                if (field != null)
                    id = field.getInt(null);
            }
        } catch (final Exception e) {
            Log.e("GET_RESOURCE_BY_NAME: ", e.toString());
            e.printStackTrace();
        }
        return id;
    }
}
Sergey Glotov
  • 20,200
  • 11
  • 84
  • 98
Joseph
  • 71
  • 1
  • 1
5

Your reply to my comment helped me get a better idea of what you're trying to do.

You can probably use ViewGroup#getChildAt and ViewGroup#getChildCount to loop through various ViewGroups in your view hierarchy and perform instanceof checks on the returned Views. Then you can do whatever you want depending on the type of the child views and where they are in your hierarchy.

Rich Schuler
  • 41,814
  • 6
  • 72
  • 59
  • This seems to be the ticket! Glad the clarification helped. It hadn't crossed my mind to access the children views of my layout. Thanks a bunch for the insight. – John Tabs Aug 26 '10 at 06:14
  • a code sample: http://stackoverflow.com/questions/4184889/android-refer-to-custom-views-in-a-loop/4185818#4185818 – Someone Somewhere May 13 '11 at 20:51
2

You can use reflection on an inner class, but the syntax is packagename.R$id. Note that reflection can be very slow and you should REALLY avoid using it.

Romain Guy
  • 97,993
  • 18
  • 219
  • 200
  • I was thinking that reflection might be too expensive, and not worth it just for the convenience of not having to hand-code some items. I was hoping that there was some built-in, non-relfection-based way of accessing these ids since it seems like a common enough scenario. Thanks, at least, for the syntax on reflecting on inner classes. It's useful to know. – John Tabs Aug 23 '10 at 06:59