kiruwka
kiruwka

Reputation: 9450

Best way to provide custom view for selected list item

Goal : have completely custom layout for selected item, considering only single item can be selected at a time.

I do not want to involve getViewTypeCount/getItemViewType for selection as they are already used in this adapter for different purposes.

One obvious option is inflating custom layout to indicate selected item by modifying adapter to something like :

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
         ViewHolder holder;
         ... 
         // initialize convertView, holder, regular stuff

         // Now, the questionable part:

        if (position == mSelectedPosition) {
           // use custom layout to indicate highlight/selection
           convertView = inflater.inflate(R.layout.custom_selection_layout, parent, false);
        } else {
            // clear up selection 
            // also convertView could be recycled view and be of unexpected type 
        }
    }

It shouldn't be too bad performance-wise as only single item is selected/inflated, but the problem is that convertedView can be of two different types, and extra cast/checks are needed.
Is this approach is frowned upon ?

Another option could be : have both selected/unselected version of layout combined in item_layout and one of them hidden/shown in adapter dynamically depending on if (position == mSelectedPosition) condition. Is this a good idea ?

Ultimately, what would be the right way to do it ?

Thanks

Upvotes: 0

Views: 120

Answers (1)

natario
natario

Reputation: 25194

I would go for the first approach. Your custom layout should be applied to only one view in the entire list, so the only thing you need to do is to avoid that such view can be recycled. I'm using this approach to load dividers at specific points in the list, and I see no performance issues.

On the other hand, having - let's say so - both layouts in one and change visibilities seems not the best option to me, as your view holder would become quite big (you need to carry reference of all the views inside, I guess) to the benefit of just a single child in the whole list. All the recycled, non-selected views would each time face the position check, that would be unnecessary for most (all but one) cases.


As for identifying the view once it gets recycled, a possible approach is to use tags as well.

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

    if (position == mSelectedPosition) {
       convertView = inflater.inflate(R.layout.custom_selection_layout, parent, false);
       //here you upload convertView without the ViewHolder pattern, by using findViewById();
       //it's legit IMO because it gets called just once for the whole list.
       convertView.setTag("SELECTED_VIEW");
       return convertView;
    }

     ViewHolder holder;
     if (convertView == null || convertView.getTag("SELECTED_VIEW")) {
         //this convertView is not good. We inflate the regular layout
         convertView = inflater.inflate( ... );
     }

     //regular stuff
     ...
}

Upvotes: 1

Related Questions