Using list preference in Android
Asked Answered
S

3

31

I have a text to speech application where the user can select a language and also select a male or female voice. The problem is that for each language there are different strings used to called the male and female voice but in my preference I only have two options (male and female).

<string-array name="Language">
    <item>English (US)</item>
    <item>English (UK)</item>
    <item>French (France)</item>
    <item>Spanish (Spain)</item>
    <item>Italian</item>
</string-array>

<string-array name="languageAlias">
    <item>"en-US"</item>
    <item>"en-GB"</item>
    <item>"fr-FR"</item>
    <item>"es-ES"</item>
    <item>"it-IT"</item>
</string-array>

<string-array name="Voice">
    <item>Male</item>
    <item>Female</item>
</string-array>

<string-array name="VoiceAlias">
    <item>"usenglishmale"</item>
    <item>"usenglishfemale"</item>
    <item>"ukenglishmale"</item>
    <item>"ukenglishfemale"</item>
    <item>"eurfrenchmale"</item>
    <item>"eurfrenchfemale"</item>
    <item>"eurspanishmale"</item>
    <item>"eurspanishfemale"</item>
    <item>"euritalianmale"</item>
    <item>"euritalianfemale"</item>        
</string-array>

I'm trying to find a way to only reference the relevant male and female voiceAlias depending on the language selected. Is it possible to do this here or do I have to write some code which changes the values of the voiceAlias array depending on the language selected?

Thanks in Advance

Spoonfeed answered 26/3, 2012 at 22:31 Comment(0)
G
60

Ok, you can accomplish this with two ListPreferences and an OnPreferenceChangeListener for each. First the XML:

<ListPreference 
    android:key="language_preference"
    android:title="Language"
    android:entries="@array/Language"
    android:entryValues="@array/languageAlias"/>

<ListPreference 
    android:key="gender_preference"
    android:title="Gender"
    android:entries="@array/Voice"
    android:entryValues="@array/VoiceData"/>

Let's make a new entry in res/values/array.xml:

<string-array name="VoiceData">
    <item>0</item>
    <item>1</item>
</string-array>

And now in your extention of PreferenceActivity, we're going to take the string values which persist in your SharedPreferences and from them create a completely new entry in the SharedPreferences which gets its value from "VoiceAlias".

SharedPreferences shareprefs = getPreferenceManager().getSharedPreferences();
Resources resources = YourContext.getResources();

private void makeVoiceData() {
    String languageData = shareprefs.getString("language_preference", "en-US");
    int genderData = Integer.parseInt(shareprefs.getString("gender_preference", "0"));
    String[] voiceAlias = resources.getStringArray(R.array.VoiceAlias);

    int a = 0
    String[] languageAlias = resources.getStringArray(R.array.languageAlias);
    for (a ; a < languageAlias.length ; a++) {
        if (languageAlias[a].equals(languageData)) {
            break;
        }
    }

    shareprefs.putString("VoiceAlias", voiceAlias[(2 * a) + genderData]);
}

ListPreference language_preference = getPreference("language_preference");
ListPreference gender_preference = getPreference("gender_preference");

language_preference.setOnPreferenceChangeListener(new OnPreferenceChangeListener() {
    public boolean onPreferenceChanged(Preference preference, Object newValue) {
        shareprefs.putString("language_preference", (String) newValue);
        makeVoiceData();
    }
});

gender_preference.setOnPreferenceChangeListener(new OnPreferenceChangeListener() {
    public boolean onPreferenceChanged(Preference preference, Object newValue) {
        shareprefs.putString("gender_preference", (String) newValue);
        makeVoiceData();
    }
});
Godly answered 26/3, 2012 at 23:13 Comment(5)
Thanks, I like the approach. However what does this line of code do? voiceAlias[(2 * a) + genderData]Spoonfeed
The value of a is defined in the for loop and it represents the index of languageData within languageAlias. The loop cycles through languageAlias until it finds the value of languageData. The value of a is multiplied by two because the voices exist in pairs within voiceAlias. genderData is added to this. If the user selected male, 0 is added and the first option of the language pair is taken. If female, 1 is added.Godly
after looking a little closer at the docs, it looks like ListPreference wants to persist a String. If you find this is the case, just wrap the declaration of genderData with Integer.parseInt(shareprefs.getString...)Godly
What is getPreference()?Mandolin
Note that the SharedPreferences requires edit() and commit() or apply() to be called when editing.Chor
A
10

String arrays can use string resources. This is the easiest (and probably simplest) way to translate user values.

<string-array name="user_values">
    <item>@string/value_1</item>
    <item>@string/value_2</item>
</string-array>

See Working with Strings and String Arrays

Agatha answered 22/9, 2014 at 13:7 Comment(0)
L
-1

Sorry, I'm not able to comment on an answer yet, so I open a new one.

Instead of writing your own algorithm in order to find the index of a particular item in a String array just rely on the standard API (it's usually faster, better design and just shorter):

final int a = Arrays.binarySearch(languageAlias, languageData);

It's the same as :

int a = 0

for (a ; a < languageAlias.length ; a++) {
    if (languageAlias[a].equals(languageData) {
        break;
    }
}
Liselisetta answered 31/5, 2015 at 12:51 Comment(1)
the below is not binary search. and @gobernador, no it will not.Vespiary

© 2022 - 2024 — McMap. All rights reserved.