Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Populate Spinner that maps strings to numbers from XML in Android

In my application I need to have Spinner with set of values, for example:

  • today
  • tomorrow
  • after_tomorrow

User chooses one of it and applications send request to server. To send the request i need to encode user's choice as int value:

  • Request.TODAY = 0;
  • Request.TOMORROW = 1;
  • Request.AFTER_TOMORROW = 2;

In UI those value are localized and, more important, could be in different order, depending on locale, for example:

  • послезавтра (after_tomorrow)
  • завтра (tomorrow)
  • сегодня (today)

What I want is to have all that stuff in localizable XML (so localization team will need to edit only XML files, not code):

  • String values
  • String order

I spent some time thinking on that problem, and my solution is here.

In strings.xml:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string name="day_today">сегодня</string>
    <string name="day_tomorrow">завтра</string>
    <string name="day_after_tomorrow">послезавтра</string>
    <array name="day_values">
        <item>@string/day_after_tomorrow</item>
        <item>@string/day_tomorrow</item>
        <item>@string/day_today</item>
    </array>
</resources>

In layout.xml:

            <Spinner
                    android:layout_width="fill_parent"
                    android:layout_height="wrap_content"
                    android:id="@+id/day"
                    android:entries="@array/day_values" />

In MyActivity.java:

private int[] dayMap;
private Spinner uiDay;

private final void setupUI(Bundle savedInstanceState) {
    uiDay = (Spinner)findViewById(R.id.day);
    final TypedArray dayValues = getResources().obtainTypedArray(R.array.day_values);
    dayMap = new int[dayValues.length()];
    for (int i = 0; dayMap.length > i; ++i) {
        final int r = dayValues.getResourceId(i, 0);
        // can't use switch() since resources ids not always final since Android 4
        if (R.string.day_today == r) {
            dayMap[i] = Request.TODAY;
        } else if (R.string.day_tomorrow == r) {
            dayMap[i] = Request.TOMORROW;
        } else if (R.string.after_tomorrow == r) {
            dayMap[i] = Request.AFTER_TOMORROW;
        }
    }
    dayValues.recycle();
}

public void submitClicked(View v) {
    final int r = dayMap[uiDay.getSelectedItemPosition()];
    submitDayRequest(r);
}

I see only one bad thing in that solution - TypedArray.getResourceId() returns "resolved" id, so if some redirects will be involved entire "if" will not work.

I want to hear some opinions on that solution and advises on how it can be implemented in other ways.

Thanks!

Update1:

Another solution uses two string arrays in xml file.

strings.xml:

<string-array name="day_entries">
    <item>послезавтра</item>
    <item>завтра</item>
    <item>сегодня</item>
</string-array>
<string-array name="day_values">
    <item>after_tomorrow</item>
    <item>tomorrow</item>
    <item>today</item>
</string-array>

MyActivity.java:

private static final Map<String, Integer> DAYS;

static {
    DAYS = new HashMap<String, Integer>();
    DAYS.put("today", Request.TODAY);
    DAYS.put("tomorrow", Request.TOMORROW);
    DAYS.put("after_tomorrow", Request.AFTER_TOMORROW);
}

private Spinner uiDay;
private String[] dayValues;

private final void setupUI(Bundle savedInstanceState) {
    uiDay = (Spinner)findViewById(R.id.day);
    dayValues = getResources().getStringArray(R.array.day_values);
}

public void submitClicked(View v) {
    final int r = DAYS.get(dayValues[uiDay.getSelectedItemPosition()]);
    submitDayRequest(r);
}

layout.xml:

            <Spinner
                    android:layout_width="fill_parent"
                    android:layout_height="wrap_content"
                    android:id="@+id/day"
                    android:entries="@array/day_entries" />

What do you think about it? Is it better on not than the first one? Maybe other ways to implement such thing?

like image 582
wonder.mice Avatar asked Oct 27 '11 12:10

wonder.mice


1 Answers

I would suggest you use the second method. Localization wise its great and you're getting the desired result too.

like image 128
d3m0li5h3r Avatar answered Sep 24 '22 07:09

d3m0li5h3r