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

keyser
  • 18,829
  • 16
  • 59
  • 101
Amanni
  • 1,924
  • 6
  • 31
  • 51

3 Answers3

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();
    }
});
weston
  • 54,145
  • 21
  • 145
  • 203
gobernador
  • 5,659
  • 3
  • 32
  • 51
  • Thanks, I like the approach. However what does this line of code do? voiceAlias[(2 * a) + genderData] – Amanni Mar 26 '12 at 23:34
  • 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. – gobernador Mar 27 '12 at 01:42
  • 1
    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...)` – gobernador Mar 29 '12 at 03:09
  • 3
    What is getPreference()? – Mark B Sep 28 '13 at 16:48
  • Note that the `SharedPreferences` requires `edit()` and `commit()` or `apply()` to be called when editing. – Jeff Lockhart Aug 27 '15 at 01:35
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

Jared Rummler
  • 37,824
  • 19
  • 133
  • 148
Shoham
  • 1,079
  • 1
  • 12
  • 17
-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;
    }
}
Andy
  • 488
  • 4
  • 13