Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android: Programmatically iterate through Resource ids

Tags:

android

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);
like image 302
John Tabs Avatar asked Aug 23 '10 06:08

John Tabs


3 Answers

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;
    }
}
like image 199
Joseph Avatar answered Oct 19 '22 20:10

Joseph


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.

like image 40
Rich Schuler Avatar answered Oct 19 '22 22:10

Rich Schuler


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.

like image 45
Romain Guy Avatar answered Oct 19 '22 22:10

Romain Guy