Question

I'm stuck getting a click listener to work properly with a ListFragment. The objective is to display a list of Likes, each of which are associated with a Category. The Category will be displayed first, followed by the Likes in that Category. I have made a custom adapter that extends BaseAdapter called LikeHashMapAdapter, which displays everything as intended. Here's the getView() method:

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

    LayoutInflater inflater = (LayoutInflater) mContext
            .getSystemService(Context.LAYOUT_INFLATER_SERVICE);

    if (convertView == null) {
        convertView = inflater.inflate(R.layout.like_row, null);
    }

    LinearLayout likeWrapper = (LinearLayout) convertView.findViewById(R.id.likeWrapper);

    String category = mCategories[pos];
    ArrayList<Like> arrLikes = (ArrayList<Like>) getItem(pos);

    for(Like like: arrLikes) {
        TextView txtLike = new TextView(mContext);
        txtLike.setText(like.getKeyword());
        likeWrapper.addView(txtLike);
    }

    TextView txtLike = (TextView) convertView.findViewById(R.id.txtCategory);
    txtLike.setText(category);

    return convertView;
}

In my ListFragment I'm sorting by Category:

private LinkedHashMap<String, ArrayList<Like>> sortLikesByCategory(ArrayList<Like> arrayList) {

    // The hashmap value will be the category name, and the value will be the array of likes
    LinkedHashMap<String, ArrayList<Like>> map = new LinkedHashMap<String, ArrayList<Like>>();

    for(Like like: arrayList) {

        // If the key does not exist in the hashmap
        if(!map.containsKey(like.getCategory().getName())) {
            ArrayList<Like> listInHash = new ArrayList<Like>();
            listInHash.add(like);
            map.put(like.getCategory().getName(), listInHash);
        } else {
            // add the like to the arraylist that corresponds to the key
            ArrayList<Like> listInHash = map.get(like.getCategory().getName());
            listInHash.add(like);

        }

    }

    return map;

}

And finally setting the adapter:

final LinkedHashMap<String, ArrayList<Like>> finalLikeMap = sortLikesByCategory(finalLikes);

            getActivity().runOnUiThread(new Runnable() {
                public void run() {
                    final LikeHashMapAdapter adapter = new LikeHashMapAdapter(getActivity(),finalLikeMap);
                    setListAdapter(adapter);
                }
            });

The issue is that the entire Category section is clickable, and not just the individual Likes. Is there an easy way to fix this? Or do I need to start from scratch?

Was it helpful?

Solution

I found that the best was to accomplish this was to abandon my own code and use Android's Expandable List View adapter. Very convenient. I followed the example given at this link: http://www.androidhive.info/2013/07/android-expandable-list-view-tutorial/

There is too much code to post here, but it's similar to a standard Android adapter implementation. The docs are here: http://developer.android.com/reference/android/widget/ExpandableListView.html

OTHER TIPS

You could make each of the likes clickable by adding a click listener to them within the loop as follows:

for(Like like: arrLikes) {
    TextView txtLike = new TextView(mContext);
    txtLike.setText(like.getKeyword());
    txtLike.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            // do something when this like is clicked
        }
    });
    likeWrapper.addView(txtLike);
}

The main problem is that you combined the list items and the categories into the same view. The list view treats the category with a contents as a single item, that's why it doesn't work. What you should do instead is create two different item types: a category and an item within it. Then you will have no problem clicking the elements.

You could have the following lines in the adapter:

@Override
public int getViewTypeCount() {
    return 2; //One is for the elements, the other one is the category title
}

@Override
public int getItemViewType(int position) {
    //Here you tell the view which type of item it is  
    return positionToTypeMap.get(position);
}

@Override
public View getView(int position, View convertView, ViewGroup parent) {
    //Return different views here depending on the current item type
}

That way it's going to work as it is supposed to.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top