Android: ฉันจะรับสายจากทรัพยากรโดยใช้ชื่อได้อย่างไร


553

ฉันต้องการมี 2 ภาษาสำหรับ UI และแยกค่าสตริงสำหรับพวกเขาในไฟล์ทรัพยากรของฉันres\values\strings.xml:

<string name="tab_Books_en">Books</string>
<string name="tab_Quotes_en">Quotes</string>
<string name="tab_Questions_en">Questions</string>
<string name="tab_Notes_en">Notes</string>
<string name="tab_Bookmarks_en">Bookmarks</string>

<string name="tab_Books_ru">Книги</string>
<string name="tab_Quotes_ru">Цитаты</string>
<string name="tab_Questions_ru">Вопросы</string>
<string name="tab_Notes_ru">Заметки</string>
<string name="tab_Bookmarks_ru">Закладки</string>

ตอนนี้ฉันต้องดึงค่าเหล่านี้แบบไดนามิกในแอพของฉัน:

spec.setContent(R.id.tabPage1);
String pack = getPackageName();
String id = "tab_Books_" + Central.lang;
int i = Central.Res.getIdentifier(id, "string", pack);
String str = Central.Res.getString(i);

i = 0ปัญหาของฉันที่

ทำไมมันไม่ทำงานในกรณีของฉัน?


1
คุณแน่ใจว่า Central.lang เป็นอย่างใดอย่างหนึ่งenหรือru?
K-ballo

1
ต้องการข้อมูลเพิ่มเติมเพื่อตรวจสอบรหัสของคุณ สถานะของแต่ละ var ก่อนรับ i คืออะไร อย่างไรก็ตามคุณควรใช้การรองรับการแปลเป็นภาษาเริ่มต้นใน Android เพื่อให้ทุกอย่างง่ายขึ้น
Alin

คำตอบ:


1069

ลิงค์ที่คุณอ้างถึงดูเหมือนว่าจะทำงานกับสตริงที่สร้างขึ้นในขณะทำงาน สตริงจาก strings.xml ไม่ได้ถูกสร้างตอนรันไทม์ คุณสามารถรับพวกเขาผ่าน

String mystring = getResources().getString(R.string.mystring);

getResources()เป็นวิธีการContextเรียน หากคุณอยู่ในActivityหรือService(ซึ่งขยายบริบท) คุณสามารถใช้มันได้ในตัวอย่างนี้

นอกจากนี้ยังทราบว่าการพึ่งพาทั้งภาษาได้รับการดูแลโดยกรอบการทำงานของหุ่นยนต์ เพียงสร้างโฟลเดอร์ที่แตกต่างกันสำหรับแต่ละภาษา res/values/strings.xmlถ้าภาษาอังกฤษเป็นภาษาเริ่มต้นของคุณเพียงแค่ใส่สตริงภาษาอังกฤษเป็นภาษา แล้วสร้างโฟลเดอร์ใหม่และใส่สายรัสเซียมีชื่อเหมือนกันเข้าไปvalues-ru res/values-ru/strings.xmlจากจุดนี้เกี่ยวกับหุ่นยนต์ที่ถูกต้องเลือกอย่างใดอย่างหนึ่งขึ้นอยู่กับสถานที่อุปกรณ์สำหรับคุณอย่างใดอย่างหนึ่งเมื่อคุณโทรgetString()หรือเมื่ออ้างอิงสตริงในรูปแบบ XML @string/mystringผ่านทาง สิ่งที่มาจากสิ่งres/values/strings.xmlเหล่านี้คือทางเลือกหากคุณไม่มีโฟลเดอร์ที่ครอบคลุมสถานที่ของผู้ใช้อันนี้จะถูกใช้เป็นค่าเริ่มต้น

ดูการแปลและการจัดหาทรัพยากรสำหรับข้อมูลเพิ่มเติม


23
หากคุณอยู่ในการandroid.support.v4.app.FragmentคุณสามารถโทรgetString(R.string.mystring)โดยตรง
JaKXz

3
ฉันเป็นเพียง wodering ทำไมมันทำ (โดย google) ด้วยวิธีที่ซับซ้อนเช่นนี้? ก่อนอื่นจะได้รับ ID ตัวเลขของ mystring (จากวัตถุ R) จากนั้นรับสตริงด้วย ID นั้น และคู่ "ID-of-mystring => realValue" อยู่ที่ไหน? เท่าที่ฉันรู้ mystring => ID-of-mystring อยู่ใน R.java แต่นั่นแหละ :)
LukášŘádek

2
ตรวจสอบให้แน่ใจว่า "R" เป็นโปรเจ็กต์ R ของคุณไม่ใช่ android R
ralphgabb

2
นี่อาจเป็นคำตอบที่จำเป็น แต่ไม่ใช่คำตอบที่ถูกขอ! สำหรับการเข้าถึงทรัพยากรสตริงแบบไดนามิกโดยใช้ชื่อดูคำตอบจาก @leonvian ... ซึ่งควรจะเป็นหนึ่งใน IMO ที่ยอมรับ
Chris Hatton

321

ผมมีปัญหาเดียวกัน. แต่รหัสด้านล่างนี้ใช้งานได้สำหรับฉัน: ตรวจสอบว่าชื่อแพ็คเกจของคุณถูกต้องหรือไม่ คุณต้องอ้างถึงแพ็กเกจรูทของแอปพลิเคชัน Android ของคุณ

private String getStringResourceByName(String aString) {
      String packageName = getPackageName();
      int resId = getResources().getIdentifier(aString, "string", packageName);
      return getString(resId);
    }

9
ในกรณีที่มีใครบางคนมีเหตุผลที่ดีในการทำเช่นนี้ (ตัวอย่างเช่นไฟล์ข้อมูลมีสตริงที่กำหนดเองซึ่งตัดสินใจว่าควรจะแสดงสตริงทรัพยากรใดหรือถ้าสตริงนี้ดึงข้อมูลจากอินเทอร์เน็ต) - จากนั้นฉันอยากจะชี้ให้เห็นว่า วิธีนี้เป็นวิธีที่ถูกต้อง โดยเฉพาะอย่างยิ่งการแก้ไขส่วนหนึ่งที่ชนิดของทรัพยากรที่เป็นและไม่ได้string stringsเพราะนั่นเป็นเหตุผล (เช่นส่วนที่เหลือของ Android) ดังนั้นขอขอบคุณที่ (และอื่น ๆ ) @leonvian :-)
Ivan Vučica

2
@Sameer เพื่อรับอาร์เรย์โดยสตริงเพียงใช้: res.getStringArray (R.array.planets_array); ลองดูที่ลิงค์ทางการนี้: developer.android.com/guide/topics/resources/…
leonvian

3
เย็น. เพื่อกำจัดการประกาศแยกต่างหากวิธีนี้สามารถ "ง่าย" String someStringFromXML = getString(getResources().getIdentifier("some_string_name", "string", getPackageName()));ในลักษณะ:
สารสื่อประสาท

80

ไม่ได้มาจากกิจกรรมเท่านั้น:

    public static String getStringByIdName(Context context, String idName) {
        Resources res = context.getResources();
        return res.getString(res.getIdentifier(idName, "string", context.getPackageName()));
    }

มันใช้งานได้ดีขอบคุณ
โมซา


26

ฉันจะเพิ่มบางสิ่งบางอย่างในการแก้ปัญหาของ leonvian ดังนั้นหากโอกาสใด ๆ สตริงไม่พบในทรัพยากร (คืนค่า 0 นั่นไม่ใช่รหัสทรัพยากรที่ถูกต้อง) ฟังก์ชั่นอาจกลับบางสิ่ง:

private String getStringResourceByName(String aString) {
    String packageName = getPackageName();
    int resId = getResources()
            .getIdentifier(aString, "string", packageName);
    if (resId == 0) {
        return aString;
    } else {
        return getString(resId);
    }
}

15

วิธีการที่ดีที่สุด

App.getRes().getString(R.string.some_id)

จะทำงานได้ทุกที่ (Utils และ Models)

ฉันได้อ่านคำตอบทั้งหมดแล้วคำตอบทั้งหมดสามารถทำให้งานของคุณสำเร็จ

  • คุณสามารถใช้getString(R.string.some_string_id)ทั้งในหรือActivityFragment
  • คุณสามารถใช้Context.getString(R.string.some_string_id)ที่คุณไม่ได้มีการเข้าถึงโดยตรงgetString()วิธี กดDialogไลค์

ปัญหา

เมื่อคุณไม่Contextสามารถเข้าถึงได้เช่นเดียวกับวิธีการในUtilชั้นเรียนของคุณ

สมมติวิธีด้านล่างโดยไม่มีบริบท

public void someMethod(){
    ...
    // can't use getResource() or getString() without Context.
}

ตอนนี้คุณจะผ่านContextเป็นพารามิเตอร์ในวิธีนี้และใช้getString().

public void someMethod(Context context){
    ...
    context.getString(R.string.some_id);
}

สิ่งที่ฉันทำคือ

public void someMethod(){
    ...
    App.getAppResources().getString(R.string.some_id)
}

อะไร? มันง่ายมากที่จะใช้ทุกที่ในแอปของคุณ!

ดังนั้นนี่คือวิธีการแก้ปัญหาUtil classโดยที่คุณสามารถเข้าถึงแหล่งข้อมูลได้จากทุกที่เช่น

import android.app.Application;
import android.content.res.Resources;

public class App extends Application {
    private static Resources resources;

    @Override
    public void onCreate() {
        super.onCreate();

        resources = getResources();
    }

    public static Resources getAppResources() {
        return resources;
    }

}

เพิ่มฟิลด์ชื่อในmanifest.xml <applicationแท็กของคุณ

<application
        android:name=".App"
        ...
        >
        ...
    </application>

ตอนนี้คุณก็พร้อมแล้ว ใช้งานApp.getAppResources().getString(R.string.some_id)ได้ทุกที่ในแอป


+1 โซลูชันที่เรียบง่ายและสะอาดตา ขอให้สังเกตการสะกดคำที่ไม่ดีgetResoursesที่getResourcesจะทำให้เกิดการแทนที่ นอกจากนี้รูปแบบซิงเกิลดูเหมือนว่าไม่จำเป็นอาจข้ามได้ หน่วยความจำใดมีปัญหากับการแก้ปัญหานี้?
Xarvalus

@Xarvalus ทำให้หน่วยความจำรั่วหรือไม่
Khemraj

ในแอพของฉันใช้ได้ดี :) แค่สงสัยว่ามีใครมีปัญหากับมันไหม ฉันจะแจ้งให้ทราบหากฉันพบกับข้อผิดพลาดใด ๆ
Xarvalus

1
@Xarvalus Memory รั่วมักเกิดขึ้นในสถานที่ที่มีการใช้ตัวแปรแม้ระดับผู้ปกครองจะถูกทำลาย เช่นเดียวกับในกิจกรรมเศษเล็กเศษน้อย ฉันไม่คิดว่ามันจะเกิดขึ้นในกรณีนี้
Khemraj

14

วิธีที่ง่ายกว่าคือการใช้getString()ฟังก์ชั่นภายในกิจกรรม

String myString = getString(R.string.mystring);

การอ้างอิง: http://developer.android.com/guide/topics/resources/string-resource.html

ฉันคิดว่าฟีเจอร์นี้เพิ่มเข้ามาใน Android เวอร์ชันล่าสุดใครก็ตามที่รู้ประวัติสามารถแสดงความคิดเห็นได้


14

วิธีง่ายๆในการรับสตริงทรัพยากรจากสตริงลงใน TextView นี่ resourceName เป็นชื่อของทรัพยากร

int resID = getResources().getIdentifier(resourceName, "string", getPackageName());
textview.setText(resID);

7

หากคุณไม่มีการอ้างอิงกิจกรรมคุณสามารถใช้บริบทของคุณในลักษณะนี้:

getContext().getString(R.string.your_string_name);

4

นอกจากนี้ยังมีชุดของสตริง Android ที่กำหนดไว้ล่วงหน้าเช่น "Ok", "ยกเลิก" และอื่น ๆ อีกมากมาย - ดังนั้นคุณไม่จำเป็นต้องประกาศทั้งหมด พวกเขามีให้โดยง่ายๆ:

getString(android.R.string.ok)

(ในกรณีนี้สตริง "ตกลง") BTW นอกจากนี้ยังมีแหล่งข้อมูล Android อื่น ๆ เช่นไอคอนภาพเป็นต้น



1

คุณสามารถลองสิ่งนี้ในกิจกรรม:

getResources().getString(R.string.your string name);

ในสถานการณ์อื่น ๆ เช่นชิ้นส่วน ... ใช้

getContext().getResources().getString(R.string.your string name);

0

เพื่อความปลอดภัยคุณควรเพิ่ม: mContext.getResources (). getString (R.string.your_string);

mContext สามารถเป็น: บริบทใน onAttach () ของ Fragment หรือกิจกรรมนี้


0

หากคุณไม่ได้รับมันในกิจกรรมหรือ Fragmnet ดังนั้น:

getContext().getResources().getString(R.string.string_name);

หากคุณต้องการได้มาจากคลาสนอกกิจกรรมหรือส่วนที่คุณไม่มีบริบทของกิจกรรมให้ใช้บริบทแอปพลิเคชัน:

getApplicationContext().getResources().getString(R.string.string_name);

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