Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can I give an ID to an item in String-array?

My question is simple, yet I don't know the answer.

WHAT I WANT:

<string-array name="items_array">
        <item id="id1">Item1</item>
</string-array>

THIS IS WHAT I CURRENTLY HAVE:

<string-array name="items_array"> 
   <item>Item1</item>
</string-array>

What do I want to achieve with that is, that I want to offer in my Spinner normal names (e.g. Martin). Yet in the ID of that item, I want to have e.g. "martin93".

The ID is usefull to append it to my URL, from which I want to fetch some data. But I want the user to choice a "normal" name, instead of weird (for example FaceBook) url name.

IMPORTANT: The facebook example is just given for explanation purposes, I am trying to achieve something else, but very similar (with ID I want to fetch the real URL's name, that is not nice to read, if I'd put it directly into Spinner).

Any ideas?

like image 209
David Kasabji Avatar asked Dec 01 '14 19:12

David Kasabji


2 Answers

If it is not needed to translate IDs you could map the translatable array entries to IDs in code. Advantage of that would be that you can avoid accidential order mismatches between IDs and values. For that use string resources for every array entry:

<string-array name="my_array" translatable="false">
    <item>@string/text_1</item>
    <item>@string/test_2</item>
    ...
</string-array>

<string name="text_1">My first entry</string>
<string name="text_2">My second entry</string>
...

In code retrieve the string resources and put them as key + ID into a hash map:

val myArrayIdMap: HashMap<String, String> = java.util.HashMap()
myArrayIdMap[getString(R.string.text_1)] = "id-1"
myArrayIdMap[getString(R.string.text_2)] = "id-2"
...

To get the ID of a specific string use the map, for example if the string array is used in a spinner, the select listener could retrieve the ID:

...
override fun onItemSelected(parent: AdapterView<*>?, view: View?, position: Int, id: Long) {
    val selectedEntry: String = parent?.getItemAtPosition(position).toString()
    val id: String = myArrayIdMap.get(selectedEntry)
}
like image 86
geri Avatar answered Sep 28 '22 01:09

geri


This solution assumes that any strings can be translated and/or reused, and spinner items can be sorted any way. IDs can also be translatable, if needed.

In strings.xml:

    <string name="id_one" translatable="false">1</string>
    <string name="id_two" translatable="false">2</string>
    <string name="id_three" translatable="false">3</string>

    <string name="name_one">name one</string>
    <string name="name_two">name two</string>
    <string name="name_three">name three</string>

    <string-array name="items">
        <item>@string/name_one</item>
        <item>@string/id_one</item>

        <item>@string/name_two</item>
        <item>@string/id_two</item>

        <item>@string/name_three</item>
        <item>@string/id_three</item>
    </string-array>

Data transfer object:

public class SpinnerItem {
    //it seems better to have some kind of validation,
    //just in case name and id were mixed up in strings.xml
    public final String name;
    public final Integer id;

    public SpinnerItem(
            String name,
            Integer id
    ) {

        this.name = name;
        this.id = id;
    }
}

Adapter:

public class SpinnerAdapter extends ArrayAdapter<SpinnerItem> {

    public SpinnerAdapter(@NonNull Context context, @NonNull ArrayList<SpinnerItem> objects) {
        super(context, 0, objects);
    }

    @NonNull
    @Override
    public View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent) {
        SpinnerItem spinnerItem = getItem(position);

        TextView textView = (TextView) convertView;

        if (textView == null) {
            textView = (TextView) LayoutInflater.from(getContext()).inflate(android.R.layout.simple_spinner_item, parent, false);
        }

        textView.setText(spinnerItem.name);

        return textView;
    }

    @Override
    public View getDropDownView(int position, @Nullable View convertView, @NonNull ViewGroup parent) {
        SpinnerItem spinnerItem = getItem(position);

        TextView textView = (TextView) convertView;

        if (textView == null) {
            textView = (TextView) LayoutInflater.from(getContext()).inflate(android.R.layout.simple_spinner_dropdown_item, parent, false);
        }

        textView.setText(spinnerItem.name);

        return textView;
    }
}

This is for fragment, but it can be used in activity:

    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        final View fragmentView = inflater.inflate(R.layout.fragment_my, container, false);

        mySpinner = fragmentView.findViewById(R.id.my_spinner);

        ArrayAdapter<?> myAdapter =
                new SpinnerAdapter(
                        getContext(),
                        getSpinnerItemDTOs(R.array.items)
                );
        mySpinner.setAdapter(myAdapter);

        mySpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
            @Override
            public void onItemSelected(AdapterView<?> parentView, View selectedItemView, int position, long id) {
                useItemData();
            }

            @Override
            public void onNothingSelected(AdapterView<?> parentView) {
            }

        });

        return fragmentView;
    }

    private void useItemData() {
        SpinnerItem myDto = (SpinnerItem) mySpinner.getSelectedItem();
        //Do anything
        }
    }

    private ArrayList<SpinnerItem> getSpinnerItemDTOs(@ArrayRes int id) {
        String[] strings = getResources().getStringArray(id);
        ArrayList<SpinnerItem> spinnerItems = new ArrayList<>();

        int i = 0;
        while (i < strings.length) {
            spinnerItems.add(new SpinnerItem(
                    strings[i++],
                    Integer.parseInt(strings[i++])
            ));
        }

        return spinnerItems;
    }

like image 29
anvlad Avatar answered Sep 28 '22 02:09

anvlad