Получение всех Drawable ресурсов из объекта Resources - PullRequest
22 голосов
/ 11 июля 2010

В моем проекте Android я хочу просмотреть всю коллекцию Drawable ресурсов.Как правило, вы можете извлечь определенный ресурс только по его идентификатору, используя что-то вроде:

InputStream is = Resources.getSystem().openRawResource(resourceId)

Однако я хочу получить все ресурсы Drawable, где я не буду знать их идентификаторызаранее.Есть ли коллекция, которую я могу перебрать, или, возможно, способ получить список идентификаторов ресурсов с учетом ресурсов в моем проекте?

Или есть ли в Java способ извлечения всех значений свойств из R.drawable статический класс?

Ответы [ 10 ]

33 голосов
/ 11 июля 2010

Ладно, это немного хакерство, но это то, что я придумал с помощью Reflection.(Обратите внимание, что resources является экземпляром класса android.content.res.Resources.)

final R.drawable drawableResources = new R.drawable();
final Class<R.drawable> c = R.drawable.class;
final Field[] fields = c.getDeclaredFields();

for (int i = 0, max = fields.length; i < max; i++) {
    final int resourceId;
    try {
        resourceId = fields[i].getInt(drawableResources);
    } catch (Exception e) {
        continue;
    }
    /* make use of resourceId for accessing Drawables here */
}

Если у кого-то есть лучшее решение, которое лучше использует вызовы Android, о которых я, возможно, не знаю, я бы определенно хотелчтобы увидеть их!

8 голосов
/ 07 марта 2013

Я взял отличный ответ Мэтта Хаггинса и реорганизовал его, чтобы сделать его более общим:

public static void loadDrawables(Class<?> clz){
    final Field[] fields = clz.getDeclaredFields();
    for (Field field : fields) {
        final int drawableId;
        try {
            drawableId = field.getInt(clz);
        } catch (Exception e) {
            continue;
        }
        /* make use of drawableId for accessing Drawables here */
    }   
}

Использование:

loadDrawables(R.drawable.class);
7 голосов
/ 16 октября 2010

Я использовал getResources (). GetIdentifier для сканирования последовательно именованных изображений в моих папках ресурсов.чтобы быть в безопасности, я решил кэшировать идентификаторы изображений при первом создании активности:

    private void getImagesIdentifiers() {

    int resID=0;        
    int imgnum=1;
    images = new ArrayList<Integer>();

    do {            
        resID=getResources().getIdentifier("img_"+imgnum, "drawable", "InsertappPackageNameHere");
        if (resID!=0)
            images.add(resID);
        imgnum++;
    }
    while (resID!=0);

    imageMaxNumber=images.size();
}
5 голосов
/ 02 октября 2013

Добавьте картинку с именем aaaa и другую с именем zzzz, а затем выполните следующие действия:

public static void loadDrawables() {
  for(long identifier = (R.drawable.aaaa + 1);
      identifier <= (R.drawable.zzzz - 1);
      identifier++) {
    String name = getResources().getResourceEntryName(identifier);
    //name is the file name without the extension, indentifier is the resource ID
  }
}

Это сработало для меня.

5 голосов
/ 12 июля 2010

Если вы захотите это сделать, вы, вероятно, неправильно используете систему ресурсов.Посмотрите на активы и AssetManager, если вы хотите перебирать файлы, включенные в ваш .apk.

4 голосов
/ 17 марта 2017

Вы должны использовать папку Raw и AssetManager, но если вы хотите использовать Drawable, потому что почему бы и нет, вот как ...

Предположим, у нас очень длинный список файлов в формате JPG, и мы хотим получить все идентификаторы ресурсов без необходимости извлечения по одному (R.drawable.pic1, R.drawable.pic2, ... и т. Д.)

//first we create an array list to hold all the resources ids
ArrayList<Integer> imageListId = new ArrayList<Integer>();

//we iterate through all the items in the drawable folder
Field[] drawables = R.drawable.class.getFields();
for (Field f : drawables) {
    //if the drawable name contains "pic" in the filename...
    if (f.getName().contains("image"))
        imageListId.add(getResources().getIdentifier(f.getName(), "drawable", getPackageName()));
}

//now the ArrayList "imageListId" holds all ours image resource ids
for (int imgResourceId : imageListId) {
     //do whatever you want here
}
3 голосов
/ 11 июля 2010

Я думаю, что код отражения будет работать, но я не понимаю, зачем вам это нужно.

Ресурсы в Android статичны после установки приложения, поэтому вы можете получить список ресурсов или массив. Что-то вроде:

<string-array name="drawables_list">
    <item>drawable1</item>
    <item>drawable2</item>
    <item>drawable3</item>
</string-array>

А из вашего Activity вы можете получить его, выполнив:

getResources().getStringArray(R.array.drawables_list);
2 голосов
/ 02 ноября 2015

Просто сделайте это:

Field[] declaredFields = (R.drawable.class).getDeclaredFields();
0 голосов
/ 10 августа 2017

ИСПОЛЬЗУЙТЕ ЭТОТ МОЙ КОД

R.drawable drawableResources = new R.drawable();
Class<R.drawable> c = R.drawable.class;
Field[] fields = c.getDeclaredFields();

for (int i = 0, max = fields.length; i < max; i++) {
    final int resourceId;
    try {
        resourceId = fields[i].getInt(drawableResources);
        // call save with param of resourceId
        SaveImage(resourceId);
    } catch (Exception e) {
        continue;
    }
}

...

public void SaveImage(int resId){
    if (!CheckExternalStorage()) {
        return;
    }

    Bitmap bmp = BitmapFactory.decodeResource(getResources(), resID);
    try {
        File dir = new File(path);
        if (!dir.exists()) {
            dir.mkdirs();
        }
        OutputStream fOut = null;
        File file = new File(path, "image1.png");
        file.createNewFile();
        fOut = new FileOutputStream(file);
        bmp.compress(Bitmap.CompressFormat.PNG, 100, fOut);
        fOut.flush();
        fOut.close();
        MediaStore.Images.Media.insertImage(this.getContentResolver(), file.getAbsolutePath(), file.getName(), file.getName());
        Log.i(LOGTAG, "Image Written to Exterbal Storage");

    } catch (Exception e) {
        Log.e("saveToExternalStorage()", e.getMessage());
    }
}
0 голосов
/ 06 апреля 2016

ОП хотел рисовать, а мне нужны макеты.Это то, что я придумал для макетов.Бизнес name.startsWith позволяет мне игнорировать сгенерированные системой макеты, поэтому вам, возможно, придется немного его настроить.Это должно работать для любого типа ресурса, изменяя значение clz.

public static Map<String,Integer> loadLayouts(){
    final Class<?> clz = R.layout.class;
    Map<String,Integer> layouts = new HashMap<>();
    final Field[] fields = clz.getDeclaredFields();
    for (Field field : fields) {
        String name = field.getName();
        if (
                !name.startsWith("abc_")
                && !name.startsWith("design_")
                && !name.startsWith("notification_")
                && !name.startsWith("select_dialog_")
                && !name.startsWith("support_")
        ) {
            try {
                layouts.put(field.getName(), field.getInt(clz));
            } catch (Exception e) {
                continue;
            }
        }
    }
    return layouts;
}
...