AndroidのRクラスをコレクションにする
動的にリソースにアクセスしたいとか、リソース配列を作るのにlist = {R.xx.xxxx1, R.xx.xxxx2, ....}とかするのが面倒なときとかはRクラスをコレクションにするといい。AndroidはリフレクションNGとか誰かが言ってた気がするけどまぁいいや。
例:ImageButtonの画像をランダムに変更するアプリの場合
Rクラスを覗く
Rクラスはresディレクトリのディレクトリ名で内部クラスを持っている。
フィールド名はディレクトリ以下のファイル名になっている
つまり、内部クラスの名前とフィールド名が分かればOK
/* AUTO-GENERATED FILE. DO NOT MODIFY. * * This class was automatically generated by the * aapt tool from the resource data it found. It * should not be modified by hand. */ package com.example; public final class R { public static final class attr { } public static final class drawable { public static final int icon=0x7f020000; public static final int up29671=0x7f020001; public static final int up29673=0x7f020002; public static final int up29674=0x7f020003; public static final int up29676=0x7f020004; public static final int up29692=0x7f020005; public static final int up29706=0x7f020006; } public static final class id { public static final int ImageButton01=0x7f050000; } public static final class layout { public static final int main=0x7f030000; } public static final class string { public static final int app_name=0x7f040001; public static final int hello=0x7f040000; } }
リソースをコレクションにする
Rクラスの内部クラスの一覧を取得するにはPackage#getClasses ※ここでandroid.R.getClassesとかやると楽しいかもしれないが幸せにはなれない
今回はイメージだけ必要なので、クラス名をdrawableに限定する。音楽をランダムに再生したいとかなら"raw"とかにする
Class#getFieldsでディレクトリ内のファイル名が取得できる
取得したものをコレクションに格納すれば出来上がり。
今後リソースが100個に増えたりとか、名前が変わったとかでもソースの改修は必要ない。
MapとList両方があるけど、今回はListしか使わない。
// Rクラスの全ての内部クラスを取得 Class<?>[] classes = com.example.R.class.getClasses(); for (Class<?> cls : classes) { // 内部クラスがdrawbleならコレクションを作る if (cls.getSimpleName().equals("drawable")) { Field[] fields = cls.getFields(); String name; for (Field field : fields) { try { name = field.getName(); if(name.equals("icon")){ //iconは無視 continue; } // drawableコレクションに格納 this.drawableMap.put(field.getName(), ((Integer) field .get(field.getName()))); this.drawableList.add((Integer) field.get(field .getName()));
ソース
package com.example; import java.lang.reflect.Field; import java.util.ArrayList; import java.util.HashMap; import java.util.Random; import android.app.Activity; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.os.Bundle; import android.util.Log; import android.view.View; import android.view.View.OnClickListener; import android.widget.ImageButton; public class S_RTest extends Activity { private ImageButton button; private HashMap<String, Integer> drawableMap; private ArrayList<Integer> drawableList; /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); this.drawableMap = new HashMap<String, Integer>(); this.drawableList = new ArrayList<Integer>(); createDrawbleCollection(); displayCollection(); this.button = (ImageButton)findViewById(R.id.ImageButton01); setImage(); this.button.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { button.getId(); setImage(); } }); } public void setImage(){ Random rand = new Random(); //リソースIDをランダムに取得 Bitmap bitmap = BitmapFactory.decodeResource(getResources(), drawableList.get(rand.nextInt(drawableList.size()))); //画像を200,200にリサイズ Bitmap resize = Bitmap.createScaledBitmap (bitmap, 200, 200, false); button.setImageBitmap(resize); } public void createDrawbleCollection() { // Rクラスの全ての内部クラスを取得 Class<?>[] classes = com.example.R.class.getClasses(); for (Class<?> cls : classes) { // 内部クラスがdrawbleならコレクションを作る if (cls.getSimpleName().equals("drawable")) { Field[] fields = cls.getFields(); String name; for (Field field : fields) { try { name = field.getName(); if(name.equals("icon")){ //iconは無視 continue; } // drawableコレクションに格納 this.drawableMap.put(name, ((Integer) field .get(name))); this.drawableList.add((Integer) field.get(name)); } catch (IllegalArgumentException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } } } } } public void displayCollection() { for (String key : this.drawableMap.keySet()) { Log.v("map", key + ":" + this.drawableMap.get(key)); } for (Integer val : this.drawableList) { Log.v("list", String.valueOf(val)); } } }