0

From a list view in a fragment contained in a TabHost, I have implemented a CAB as well as highlighting of the longPressed (selected) row. This works perfectly running >= api 14. However, I am supporting api > 8.

In api 8 I am seeing strange behaviour whereby the wrong view is being highlighted in the list when longPressing a list item, sometimes. It seems that depending on how many rows are visible in the list determines whether or not the highlighting will work. This is very baffling because the method that performs the background color change is using the view that was passed in to it and the position parameter is indeed correct.

Is this a bug or am I missing something?

 listView.setAdapter(
            new myAdapter(
                    inflater,
                    tvSeason)
    );
    listView.setOnItemLongClickListener( new AdapterView.OnItemLongClickListener() {
        @Override
        public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
            if (mActionMode != null) {
                dismissActionMode();
                return false;
            }
            // Start the CAB using the ActionMode.Callback defined above
            mActionMode = getSherlockActivity().startActionMode(mActionModeCallback);
            view.setSelected(true);

            selectedTvEpisode = (TvEpisode)listView.getAdapter().getItem(position);
            mActionMode.setTitle(MyApp.getResourceString(R.string.tv_episode_number, selectedTvEpisode.getNumber()));

    view.setBackgroundColor(getActivity().getResources().getColor(R.color.lime));
            selectedView = view;
            return true;
        }
    });
JohnRock
  • 6,795
  • 15
  • 52
  • 61

1 Answers1

1

Careful, do not set the views background color like that! Remember: the views in ListView get recycled. What you should do is to get your data item, set a selected flag, and then call notifyDataSetChanged() in the Adapter. Set the background according to the selected flag in Adapter.getView().

SimonSays
  • 10,867
  • 7
  • 44
  • 59
  • Yes, I am aware of the recycling, but I thought a view would not be recycled while it was visible and a user was longPressing it... – JohnRock Oct 02 '14 at 20:52
  • No it's not, but the right approach is still to handle the selected/unselected on data side and let the adapter take car of the background. I'm pretty sure this will fix your problem. – SimonSays Oct 02 '14 at 21:03
  • I tried your suggested approach, and I agree it is the right way to do it. However same problem. Testing on API 8 the view that gets highlighted is off by 1 or two rows – JohnRock Oct 02 '14 at 21:40
  • Be sure that the positions that you set as select are right. Add a log to `getView()` that outputs maybe the name of the item and the selection status. Does it fit? Are the correct items marked as selected in the data? – SimonSays Oct 02 '14 at 22:20
  • Marking your answer as correct because your advice did help me solve it by setting the background color conditionally inside the Adapter.getView() method. – JohnRock Oct 03 '14 at 03:30
  • The way I solved it however, was to keep the state of the selected itemId in the parent fragment and expose that id via an interface and add a reference to it in the adapter. Then in getView() I use the interface method to compare the selectedId in the fragment with the id for the data inside the current view. This is how I determine whether to highlight the row. **I could not rely on the 'isSelected' flag of the view because when testing in API 8 the views get mixed up and are not reliable. THe method you described worked perfect in > 14 but not in 8. Maybe this is a bug – JohnRock Oct 03 '14 at 03:32