Ссылка на строку в ресурсе строкового массива с помощью xml

257

У меня есть настройки, где вы можете включить / отключить, какие элементы будут отображаться в меню. 17 предметов. Я создал строковый массив в values ​​/ arrays.xml с заголовками для каждого из этих 17 элементов.

У меня есть файл preferences.xml, в котором есть макет для моего файла настроек, и я хотел бы сослаться на один элемент из массива строк, чтобы использовать его в качестве заголовка.

Как я могу это сделать?

В справочнике разработчика Android я вижу, как я могу ссылаться на одну строку с XML, но не как я могу ссылаться на строку из ресурса массива в XML.

Jorsher
источник

Ответы:

332

Короче говоря: я не думаю, что вы можете, но, кажется, есть обходной путь .

Если вы посмотрите на ресурс Android здесь:

http://developer.android.com/guide/topics/resources/string-resource.html

Вы видите, что в разделе «массив» (по крайней мере, строковый массив) «RESOURCE REFERENCE» (как вы получаете из XML) не указывает способ адресации отдельных элементов. Вы даже можете попробовать в своем XML использовать "@ array / yourarrayhere". Я знаю, что во время разработки вы получите первый предмет. Но это бесполезно, если вы хотите использовать, скажем ... второе, конечно.

ОДНАКО, есть трюк, который вы можете сделать. Посмотреть здесь:

Ссылка на строку XML в массиве XML (Android)

Вы можете «обмануть» (не совсем) определение массива, обратившись к независимым строкам ВНУТРИ определения массива. Например, в вашем strings.xml:

<string name="earth">Earth</string>
<string name="moon">Moon</string>

<string-array name="system">
    <item>@string/earth</item>
    <item>@string/moon</item>
</string-array>

Используя это, вы можете использовать «@ string / earth» и «@ string / moon» в своих полях «android: text» и «android: title» XML, и все же вы не потеряете возможность использовать массив определение для любых целей, которые вы намеревались в первую очередь.

Кажется, работает здесь, на моем затмении. Почему бы вам не попытаться сказать нам, если это работает? :-)

davidcsb
источник
32
если бы мы могли только дать nameтеги <item> s ... * sigh *
Какой-нибудь Noob Student
2
Только что попробовал! Определял массив по умолчанию, strings.xmlно не внес его, values-frи массив все еще обновлялся до французской версии. Так неправильно .. но круто это работает!
Бланделл
1
Быстрый совет любому: двойной щелчок по «земле» выделит землю. Двойной щелчок по луне в @ string / moon выделит только луну. Таким образом, если вы дублируете первый элемент несколько раз при построении массива, вы можете легко скопировать и вставить между вашими отдельными строками и массивом строк. Может помочь в ускорении создания вашего строкового массива :)
ArtOfWarfare
2
Просто хочу знать, если этот подход вызывает худшую производительность, чем если бы я объявил строки в массиве, как они, но не используя ссылки?
Алекс Бонель
1
@ AlexBonel интересный вопрос, и я, честно говоря, не знаю. Даже если это произойдет, я думаю, что мы должны оставить этот тип микро-оптимизации для компилятора. В любом случае, они не заканчиваются где-нибудь внизу? Я предполагаю, что они делают, но я не уверен. По крайней мере, на более высоком уровне в цепочке Android, я знаю, что вы можете полностью разобрать APK с помощью apktool, и он восстановит исходные имена строковых ключей, что означает, что ссылочные объявления, как и выше, сохраняются. Но мне сейчас не очень интересна эта область, поэтому я не могу ответить на ваш вопрос. Это хороший вопрос.
davidcsb
217

Может быть, это поможет:

String[] some_array = getResources().getStringArray(R.array.your_string_array)

Таким образом, вы получаете список массивов в виде строки [], а затем выбираете любой i, some_array [i].


источник
10
Я понимаю, как получить ресурс массива. Это не позволяет мне ссылаться на элемент из массива в формате XML.
Jorsher
1
Ах, прости. Я неправильно понял. Ну, это должно быть в макете XML? Если заголовок меняется в зависимости от выбора пользователя, почему бы просто не сделать это в файле .java. Например .setText (some_array [i]).
2
Потому что макет предпочтений в формате XML. Java загружает меню с пунктами, которые «включены» в настройках. Напечатав 17 проверок на предпочтения, и последующий код, чтобы добавить его в просмотр списка, кажется мне излишним и небрежным.
Jorsher
Это было полезно, когда я создавал массив-адаптер из массива xml в моей папке значений
EHarpham
Я нашел это полезным, когда нужно получить значение по умолчанию при получении предпочтения: String myPref = preferences.getString(context.getResources().getString(R.string.my_pref), some_array [0]);где my_pref ранее было установлено какое-то значение some_array [x]
Al Lelopath
67

Лучшим вариантом было бы просто использовать массив, возвращаемый ресурсом, как массив, что означает:

getResources().getStringArray(R.array.your_array)[position]

Это сокращенный подход вышеупомянутых подходов, но он работает так, как вы хотите. В противном случае Android не обеспечивает прямую индексацию XML для массивов на основе XML.

Amitesh
источник
1
@ Benjiko99 спасибо за обнаружение ошибки, изменили ее соответственно.
Амитеш
Это самый лаконичный способ сделать это. +1!
suomi35
1
это может показаться более кратким, но если кто-то или переводчик изменят порядок массива в файле строк, вы в конечном итоге будете использовать неправильную строку.
newDeveloper
9

К сожалению:

  • Кажется, вы не можете ссылаться на один элемент из массива в values ​​/ arrays.xml с XML. Конечно, вы можете в Java, но не XML. Информация об этом отсутствует в справочнике разработчика Android, и я не смог найти ничего другого.

  • Кажется, вы не можете использовать массив в качестве ключа в макете настроек. Каждый ключ должен быть одним значением со своим собственным именем ключа.

Чего я хочу добиться: я хочу иметь возможность перебрать 17 предпочтений, проверить, отмечен ли пункт, и, если это так, загрузить строку из массива строк для этого имени предпочтения.

Вот код, который я надеялся завершить эту задачу:

SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(getBaseContext());  
ArrayAdapter<String> itemsArrayList = new ArrayAdapter<String>(getBaseContext(),   android.R.layout.simple_list_item_1);  
String[] itemNames = getResources().getStringArray(R.array.itemNames_array);  


for (int i = 0; i < 16; i++) {  
    if (prefs.getBoolean("itemKey[i]", true)) {  
        itemsArrayList.add(itemNames[i]);  
    }  
} 

Что я сделал:

  • Я установил одну строку для каждого из элементов и сослался на отдельные строки в. Я использую ссылку на одну строку для заголовков флажка макета настроек и массив для моего цикла.

  • Чтобы пройти через настройки, я просто назвал ключи, такие как key1, key2, key3 и т. Д. Поскольку вы ссылаетесь на ключ со строкой, у вас есть возможность «построить» имя ключа во время выполнения.

Вот новый код:

for (int i = 0; i < 16; i++) {  
        if (prefs.getBoolean("itemKey" + String.valueOf(i), true)) {  
        itemsArrayList.add(itemNames[i]);  
    }  
}
Jorsher
источник
1

Другой способ сделать это - определить массив ресурсов в strings.xml, как показано ниже.

<?xml version="1.0" encoding="utf-8"?> <!DOCTYPE resources [
    <!ENTITY supportDefaultSelection "Choose your issue">
    <!ENTITY issueOption1 "Support">
    <!ENTITY issueOption2 "Feedback">
    <!ENTITY issueOption3 "Help">
    ]>

а затем определение массива строк с использованием вышеуказанных ресурсов

<string-array name="support_issues_array">
        <item>&supportDefaultSelection;</item>
        <item>&issueOption1;</item>
        <item>&issueOption2;</item>
        <item>&issueOption3;</item>
    </string-array>

Вы можете ссылаться на ту же строку в других xmls, сохраняя DRY нетронутыми. Преимущество, которое я вижу, состоит в том, что с одним изменением значения это повлияет на все ссылки в коде.

Amruta-Пани
источник