Android, dizeden kaynak kimliği alınıyor mu?


159

Sınıflarımdan birinde bir yönteme bir kaynak kimliği geçmek gerekiyor. Hem başvurunun işaret ettiği kimliği kullanması hem de dizeye ihtiyacı vardır. Bunu en iyi nasıl başarmalıyım?

Örneğin:

R.drawable.icon

Bunun tamsayı kimliği almak gerekiyor, ama ben de "simge" dizeye erişim gerekir.

Yönteme geçmek zorunda olduğum tek şey "simge" dizesi olması tercih edilir.


dahili depolama birimine kaydedilmiş dosyaları almak benzer şekilde mümkün mü? Ben galeriye (yerine adaptör olduğunu düşündüm) yerleri yerine ids dizi sağlamalıdır çünkü sorun var .. teşekkürler
Ewoks

@Ewoks: Dahili depolama biriminde kimlikleri yok. Bunlar sadece görüntülerdir, eğer bunları bir grup Görüntü nesnesine yüklemeniz ve bunları geçmeniz gerekiyorsa, yeni bir soru başlatmak isteyebilirsiniz.
Hamid

Yanıtlar:


172

@EboMike: Bunun Resources.getIdentifier()var olduğunu bilmiyordum .

Projelerimde bunu yapmak için aşağıdaki kodu kullandım:

public static int getResId(String resName, Class<?> c) {

    try {
        Field idField = c.getDeclaredField(resName);
        return idField.getInt(idField);
    } catch (Exception e) {
        e.printStackTrace();
        return -1;
    } 
}

R.drawable.iconKaynak tamsayı değerinin değerini almak için şu şekilde kullanılır

int resID = getResId("icon", R.drawable.class); // or other resource class

Daha önce Resources.getIdentifier()yaptığım gibi yansımayı kullanmaktan daha yavaş olduğunu söyleyen bir blog yazısı buldum . Şuna bir bak .


8
@Macarse: Şu anda, getIdentifier()iki yansıma araması yapmak zorunda. Yukarıdaki örneğinizde, getIdentifier()almak için yansımayı Drawable.class, ardından kaynak kimliğini almak için başka bir yansımayı arayın. Bu, hız farkını açıklar. Bununla birlikte, özellikle hızlı değildir ve bu nedenle gerçekten önbelleğe alınması gerekmez (özellikle bir döngüde veya a'daki satırlar için ListView). Yansıtma yaklaşımının büyük sorunu, Android'in iç kısımları hakkında gelecekteki sürümlerde değişebilecek varsayımlar yapmasıdır.
CommonsWare

1
@CommonsWare: Doğru. Android'in nasıl uygulandığını kontrol ediyordum ve yerel bir çağrı olmakla bitiyor. gitorious.org/android-eeepc/base/blobs/… => gitorious.org/android-eeepc/base/blobs/…
Macarse

3
Bunun yerine kimlikleri olan bir tamsayı dizisi kullanırdım. Kimlikler için dize kullanmak doğru yaklaşım gibi gelmiyor.
EboMike

9
Neden contextparametre?
Rudey

14
Çağrı getId olmalıdır ("simge", R.drawable.class); getResId ("simge", bağlam, Drawable.class);
Smeet

80

Kaynak kimliğini almak için bu işlevi kullanabilirsiniz.

public static int getResourceId(String pVariableName, String pResourcename, String pPackageName) 
{
    try {
        return getResources().getIdentifier(pVariableName, pResourcename, pPackageName);
    } catch (Exception e) {
        e.printStackTrace();
        return -1;
    } 
}

Yani bu şekilde çekilebilir çağrı fonksiyonu almak istiyorsanız

getResourceId("myIcon", "drawable", getPackageName());

ve dize için buna şöyle diyebilirsiniz

getResourceId("myAppName", "string", getPackageName());

Oku bunu


11
Başka bir işlev çağıran ve olası bir istisnayı "işleyen" bir işlev oluşturmanın anlamı nedir? Doğrudan getResources (). GetIdentifier () öğesini çağırın.
Ricardo Meneghin Filho

37

Bu @Macarse cevabını temel alır.

Kaynak kimliği daha hızlı ve kod dostu bir şekilde almak için bunu kullanın.

public static int getId(String resourceName, Class<?> c) {
    try {
        Field idField = c.getDeclaredField(resourceName);
        return idField.getInt(idField);
    } catch (Exception e) {
        throw new RuntimeException("No resource ID found for: "
                + resourceName + " / " + c, e);
    }
}

Misal:

getId("icon", R.drawable.class);

30

Kaynak adından bir uygulama kaynak kimliği almak oldukça yaygın ve iyi yanıtlanmış bir sorudur.

Kaynak adından yerel bir Android kaynak kimliği nasıl alınır , daha az yanıtlanır. Kaynak adına göre bir Android çekilebilir kaynak almak için benim çözüm:

public static Drawable getAndroidDrawable(String pDrawableName){
    int resourceId=Resources.getSystem().getIdentifier(pDrawableName, "drawable", "android");
    if(resourceId==0){
        return null;
    } else {
        return Resources.getSystem().getDrawable(resourceId);
    }
}

Yöntem, diğer kaynak türlerine erişmek için değiştirilebilir.


Şimdi .getResources (). getDrawable kullanımdan kaldırıldı if(android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP){ return mContext.getDrawable(resourceId); } else { return mContext.getResources().getDrawable(resourceId); }
Evilripper

11

Bir dize ve int eşleştirmeniz gerekiyorsa, bir Haritaya ne dersiniz?

static Map<String, Integer> icons = new HashMap<String, Integer>();

static {
    icons.add("icon1", R.drawable.icon);
    icons.add("icon2", R.drawable.othericon);
    icons.add("someicon", R.drawable.whatever);
}

9

Sen kullanabilirsiniz Resources.getIdentifier()size yani XML dosyalarında, kullanmak gibi dize için biçimini kullanmak gerekir rağmen, package:drawable/icon.


Aşağıdaki cevabım bunun tersi. Kaynak kimliğini iletin ve sonra getResourceEntryName(id)dize adını bulmak için kullanın . Daha uzun metinden "simge" bulmak için karışıklık yok.
Steve Waring

8

Bunu beğendim, benim için çalışıyor:

    imageView.setImageResource(context.getResources().
         getIdentifier("drawable/apple", null, context.getPackageName()));

7
Simple method to get resource ID:

public int getDrawableName(Context ctx,String str){
    return ctx.getResources().getIdentifier(str,"drawable",ctx.getPackageName());
}

1
Cevabınıza biraz daha bilgi verirseniz daha iyi olur.
xMRi

6

Dizeden kaynak kimliği almanın basit bir yolu. Burada resourceName , XML dosyasında da bulunan çekilebilir klasördeki ImageView kaynağının adıdır.

int resID = getResources().getIdentifier(resourceName, "id", getPackageName());
ImageView im = (ImageView) findViewById(resID);
Context context = im.getContext();
int id = context.getResources().getIdentifier(resourceName, "drawable",
context.getPackageName());
im.setImageResource(id);

Teşekkürler adam gerçekten yardımcı oldu .. Ben çok aradım ve işe yaramadı. Cevabınızı görerek, ikinci parametrenin getIdentifierolması gerektiğini buldum id. Bu android dev sitesinde bile bahsedilmedi. bu bilgiyi nereden aldın?
Prakash GPz

4

Sadece bir parametreyi geçmek istediğinizi ve hangisinin önemli olduğunu görünmediğinizi söylediğinizden, kaynak tanımlayıcısını geçirebilir ve daha sonra bunun için dize adını öğrenebilirsiniz:

String name = getResources().getResourceEntryName(id);

Bu, her iki değeri elde etmenin en etkili yolu olabilir. Daha uzun bir dizeden yalnızca "simge" bölümünü bulmak için uğraşmak zorunda değilsiniz.


2

Res / layout / my_image_layout.xml dosyasında

<LinearLayout ...>
    <ImageView
        android:id="@+id/row_0_col_7"
      ...>
    </ImageView>
</LinearLayout>

Bu ImageView'i @ + id değerine göre yakalamak için java kodunuzun içinde bunu yapın:

String row = "0";
String column= "7";
String tileID = "row_" + (row) + "_col_" + (column);
ImageView image = (ImageView) activity.findViewById(activity.getResources()
                .getIdentifier(tileID, "id", activity.getPackageName()));

/*Bottom code changes that ImageView to a different image. "blank" (R.mipmap.blank) is the name of an image I have in my drawable folder. */
image.setImageResource(R.mipmap.blank);  

2

Kotlin yaklaşımı

inline fun <reified T: Class<R.drawable>> T.getId(resourceName: String): Int {
            return try {
                val idField = getDeclaredField (resourceName)
                idField.getInt(idField)
            } catch (e:Exception) {
                e.printStackTrace()
                -1
            }
        }

Kullanımı:

val resId = R.drawable::class.java.getId("icon")

1

MonoDroid / Xamarin.Android'de şunları yapabilirsiniz:

 var resourceId = Resources.GetIdentifier("icon", "drawable", PackageName);

Ancak GetIdentifier Android'de önerilmediğinden - Reflection'ı şu şekilde kullanabilirsiniz:

 var resourceId = (int)typeof(Resource.Drawable).GetField("icon").GetValue(null);

Burada bir denemek / yakalamak veya geçen dizeleri doğrulamak öneririz.


1

Dize kaynak adından Drawable id almak için bu kodu kullanıyorum:

private int getResId(String resName) {
    int defId = -1;
    try {
        Field f = R.drawable.class.getDeclaredField(resName);
        Field def = R.drawable.class.getDeclaredField("transparent_flag");
        defId = def.getInt(null);
        return f.getInt(null);
    } catch (NoSuchFieldException | IllegalAccessException e) {
        return defId;
    }
}
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.