Android รับ ID ทรัพยากรจากสตริงหรือไม่


158

ฉันต้องส่ง ID ทรัพยากรไปยังวิธีการในชั้นเรียนของฉัน มันจำเป็นต้องใช้ทั้ง id ที่จุดอ้างอิงและยังต้องการสตริง ฉันควรทำสิ่งนี้ให้สำเร็จได้อย่างไร

ตัวอย่างเช่น:

R.drawable.icon

ฉันต้องการรับ ID จำนวนเต็มของสิ่งนี้ แต่ฉันต้องเข้าถึงสตริง "ไอคอน" ด้วย

มันจะดีกว่าถ้าทั้งหมดที่ฉันต้องผ่านไปวิธีคือสตริง "ไอคอน"


เป็นไปได้ในทำนองเดียวกันในการรับไฟล์ที่บันทึกในที่เก็บข้อมูลภายใน? ฉันมีปัญหาเพราะฉันควรจัดหารหัสของอาร์เรย์แทนสถานที่ไปยังแกลเลอรี่ของฉัน (คิดว่ามันเป็นอะแดปเตอร์) .. ขอบคุณ
Ewoks

@Ewoks: พวกเขาไม่มีรหัสในที่เก็บข้อมูลภายใน มันเป็นเพียงรูปภาพหากมีสิ่งใดที่คุณต้องการโหลดวัตถุเหล่านั้นลงในกลุ่มอิมเมจแล้วส่งต่อคุณอาจต้องการเริ่มคำถามใหม่
ฮามิด

คำตอบ:


171

@EboMike: ฉันไม่รู้ว่าResources.getIdentifier()มีอยู่จริง

ในโครงการของฉันฉันใช้รหัสต่อไปนี้เพื่อทำสิ่งนั้น:

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.iconค่าจำนวนเต็มของทรัพยากร

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

ฉันเพิ่งพบโพสต์บล็อกที่บอกว่าResources.getIdentifier()ช้ากว่าการใช้ภาพสะท้อนเหมือนที่ฉันทำ ลองดูสิ


8
@Macarse: ปัจจุบันgetIdentifier()ต้องทำการค้นหาสองครั้ง ในตัวอย่างของคุณด้านบนgetIdentifier()จะใช้การสะท้อนเพื่อรับDrawable.classจากนั้นการค้นหาการสะท้อนอีกครั้งเพื่อรับ ID ทรัพยากร นั่นจะอธิบายถึงความแตกต่างของความเร็ว ที่ถูกกล่าวว่าไม่รวดเร็วโดยเฉพาะและดังนั้นจึงจำเป็นต้องถูกแคช (โดยเฉพาะอย่างยิ่งถ้าใช้ในการวนรอบหรือแถวใน a ListView) และปัญหาใหญ่ของวิธีการไตร่ตรองคือว่ามันตั้งสมมติฐานเกี่ยวกับ internals ของ Android ที่อาจมีการเปลี่ยนแปลงในการเปิดตัวในอนาคต
CommonsWare

1
@CommonsWare: ถูกต้อง ฉันกำลังตรวจสอบว่า Android ใช้งานอย่างไรและจะจบลงด้วยการเป็นเจ้าของภาษา gitorious.org/android-eeepc/base/blobs/… => gitorious.org/android-eeepc/base/blobs/…
Macarse

3
ฉันจะใช้อาร์เรย์จำนวนเต็มกับรหัสแทน การใช้สตริงสำหรับ ID นั้นดูไม่เหมือนวิธีที่ถูกต้อง
EboMike

9
ทำไมcontextพารามิเตอร์
Rudey

14
การโทรควรเป็น getId ("ไอคอน", R.drawable.class) ไม่ getResId ("ไอคอน", บริบท, Drawable.class);
Smeet

80

คุณสามารถใช้ฟังก์ชันนี้เพื่อรับ ID ทรัพยากร

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

ดังนั้นถ้าคุณต้องการฟังก์ชั่นการโทรแบบdrawableเช่นนี้

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

และสำหรับสายคุณสามารถเรียกมันว่าสิ่งนี้

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

อ่านนี่


11
อะไรคือจุดที่ทำให้ฟังก์ชั่นที่เรียกอีกอย่างหนึ่งว่า "จัดการ" เป็นข้อยกเว้นที่เป็นไปได้? โทรหา getResources (). getIdentifier () โดยตรง
Ricardo Meneghin Filho

37

นี่เป็นไปตามคำตอบของ @Macarse

ใช้สิ่งนี้เพื่อรับรหัสทรัพยากรในวิธีที่รวดเร็วและเป็นมิตรกับรหัสมากขึ้น

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);
    }
}

ตัวอย่าง:

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

30

วิธีรับรหัสทรัพยากรแอปพลิเคชันจากชื่อทรัพยากรนั้นเป็นคำถามที่พบบ่อยและได้รับคำตอบที่ดี

วิธีรับรหัสทรัพยากรดั้งเดิมของ Androidจากชื่อทรัพยากรจะได้รับคำตอบน้อยกว่า นี่เป็นวิธีแก้ปัญหาของฉันในการรับทรัพยากร drawable Android โดยใช้ชื่อทรัพยากร:

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);
    }
}

วิธีนี้สามารถแก้ไขได้เพื่อเข้าถึงทรัพยากรประเภทอื่น


ตอนนี้. getResources (). getDrawable เลิกใช้แล้ว 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

หากคุณต้องการจับคู่สตริงและ int แล้วแผนที่ล่ะ?

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

คุณสามารถใช้Resources.getIdentifier()ถึงแม้ว่าคุณจะต้องใช้รูปแบบของสายของคุณในขณะที่คุณใช้ในไฟล์ XML package:drawable/iconของคุณคือ


คำตอบของฉันด้านล่างคือสิ่งที่ตรงกันข้าม ส่งรหัสทรัพยากรแล้วใช้getResourceEntryName(id)เพื่อค้นหาชื่อสตริง ไม่มีปัญหาในการค้นหา "ไอคอน" จากข้อความที่ยาวขึ้น
Steve Waring

8

ฉันไม่ชอบสิ่งนี้มันใช้ได้ผลสำหรับฉัน:

    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
จะดีกว่าถ้าคุณให้ข้อมูลเพิ่มเติมกับคำตอบของคุณ
xMRi

6

วิธีง่ายๆในการรับ ID ทรัพยากรจากสตริง นี่resourceNameเป็นชื่อของทรัพยากร ImageView ในโฟลเดอร์ drawable ซึ่งรวมอยู่ในไฟล์ XML เช่นกัน

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);

ขอบคุณผู้ชายมันมีประโยชน์จริง ๆ .. ฉันค้นหามากและไม่ได้ทำงาน โดยเห็นคำตอบของคุณฉันพบว่าพารามิเตอร์ตัวที่สองสำหรับการจะต้องมีการgetIdentifier idนี่ไม่ได้กล่าวถึงในเว็บไซต์ dev Android คุณได้รับข้อมูลนั้นอยู่ที่ไหน
Prakash GPz

4

เนื่องจากคุณบอกว่าคุณต้องการส่งเพียงพารามิเตอร์เดียวเท่านั้น แต่ดูเหมือนว่าไม่ได้มีความสำคัญคุณสามารถส่งตัวระบุทรัพยากรเข้ามาแล้วค้นหาชื่อสตริงของมันได้ดังนี้:

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

นี่อาจเป็นวิธีที่มีประสิทธิภาพที่สุดในการรับค่าทั้งสอง คุณไม่ต้องยุ่งไปกับการค้นหาเพียงส่วน "ไอคอน" จากสตริงอีกต่อไป


2

ใน res / layout / my_image_layout.xml ของคุณ

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

หากต้องการคว้า ImageView นั้นโดยใช้ค่า @ + id ภายในโค้ดจาวาของคุณให้ทำดังนี้:

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

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
            }
        }

การใช้งาน:

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

1

ใน MonoDroid / Xamarin.Android คุณสามารถทำได้:

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

แต่เนื่องจาก GetIdentifier ไม่แนะนำใน Android - คุณสามารถใช้ Reflection ดังนี้:

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

ที่ฉันแนะนำให้ลอง / จับหรือตรวจสอบสตริงที่คุณผ่าน


1

สำหรับการรับ Drawable id จากชื่อทรัพยากร String ฉันใช้รหัสนี้:

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;
    }
}
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.