0

The problem is simple. I've implemented a Navigation Drawer in Android. Now, I have a menu, where each item is an item of a string-array in strings.xml. A fragment is created every time the user clicks on one of the menu items. Within the fragment class I'd like to switch among the items in order to populate the main content with the appropriate information. The only way I know is check the position of the item, but what happens if, in the future, I'll add a further item? I will need to change all the position values in my code.

So, I wonder if there is a way to assign a sort of ID to each element. I've read here to define a separate string for each of them, but how can I check the values? I tried in the following way, but it gives me a Constant expression required error:

Resources resources = getResources();
    switch(item_string) {
        case resources.getString(R.string.item1):
            //TODO
        case resources.getString(R.string.item2):
            //TODO
        ...
Community
  • 1
  • 1
redcrow
  • 1,743
  • 3
  • 25
  • 45
  • For string-arrays, you should use indexes. For separate strings, you can use reflection. For a database table... I assume you know how to manage it. – Phantômaxx Jun 19 '15 at 15:28
  • 2
    oh come on ... use data.json in raw/assets ... it will save you a lots of trouble ... you need simple array: use string-arrays ... you need some structured data use: xml/json/database – Selvin Jun 19 '15 at 15:29
  • May be you can setTag for the each item (from the drawerlist adapter's getTag method) and use it here. – km86 Jun 19 '15 at 15:32
  • Or define another array with same length as your existing one and define all id's in this new array. Use your navigation item position from existing array to get id value from this new array. Make sure to keep these 2 arrays in sync. – prashant Jun 19 '15 at 15:35
  • @Selvin: could you plese be more accurate? – redcrow Jun 19 '15 at 15:56
  • `[{"name": "item1", "isfragment" :true, "description" : "some_desc", "icon_res_name" : "iconid1", "i_dont_know_fragment_class" : "com.app.Fragment1", .... }, ... ]` ... load it to some array of model (fx. Item class) ... then there will be no `swich case` but model itself will have all usefull information ... obviously string array is not enough info ... array of Item should have – Selvin Jun 19 '15 at 16:07

1 Answers1

0

As suggested by Selvin, I've created a JSON file in assets/ in which each element of the JSON array corresponds to a menu item including three fields (id, name and icon), e.g.:

[
    {"id": 1, "name": "item1", "icon": "icon1"}, 
    {"id": 2, "name": "item2", "icon": "icon2"}, 
    {"id": 3, "name": "item3", "icon": "icon3"}, 
    {"id": 4, "name": "item4", "icon": "icon4"}
]

Then, I firstly created an Item class to map the JSON object:

public class Item {
    private int id;
    private String name;
    private String icon;

    public Item(JSONObject object) {
        try {
            this.id = object.getInt("id");
            this.name = object.getString("name");
            this.icon = object.getString("icon");
        } catch (JSONException e) {
            e.printStackTrace();
        }
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getIcon() {
        return icon;
    }

    public void setIcon(String icon) {
        this.icon = icon;
    }

    // Factory method to convert an array of JSON objects into a list of objects
    // User.fromJson(jsonArray);
    public static ArrayList<Item> fromJson(JSONArray jsonObjects) {
    ArrayList<Item> items = new ArrayList<Item>();
    for (int i = 0; i < jsonObjects.length(); i++) {
        try {
            items.add(new Item(jsonObjects.getJSONObject(i)));
        } catch (JSONException e) {
            e.printStackTrace();
        }
    }
    return items;
    }

}

and the corresponding adapter:

public class ItemAdapter extends ArrayAdapter<Item> {

    public ItemAdapter(Context context, ArrayList<Item> items) {
        super(context, 0, items);
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {

        // Get the data item for this position
        Item item = getItem(position);
        int item_id = item.getId();
        String item_name = item.getName();
        int item_icon_id = parent.getContext().getResources().getIdentifier(item.getIcon(),
                "drawable", parent.getContext().getPackageName());

        // Check if an existing view is being reused, otherwise inflate the view
        if (convertView == null) {
            convertView = LayoutInflater.from(getContext()).inflate(R.layout.drawer_list_item, parent, false);
        }

        // Lookup view for data population
        ImageView item_icon_view = (ImageView) convertView.findViewById(R.id.item_icon);
        TextView item_name_view = (TextView) convertView.findViewById(R.id.item_name);

        // Populate the data into the template view using the data object
        item_name_view.setText(item_name);
        item_icon_view.setImageResource(item_icon_id);

        // Return the completed view to render on screen
        return convertView;
    }
}

Finally in my activity I pass the id of the selected item:

Fragment fragment = new MainFragment();
Bundle args = new Bundle();
args.putInt(MainFragment.ARG_ITEM_ID, item.getId());
args.putString(MainFragment.ARG_ITEM_NAME, item.getName());
fragment.setArguments(args);

and I switch in my fragment as in the following:

int item_id = getArguments().getInt(ARG_ITEM_ID);

switch(item_id) {
    case 1:
        [...]

    case 2:
        [...]

[...]

Hope my example can help other people.

redcrow
  • 1,743
  • 3
  • 25
  • 45