8

I am developing a tabbed application in which one of the fragments, CollectionsFragment, contains a GridView with an ImageView in each slot. I would like the to use a selector to give feedback to users when the user clicks on one of the images.

I have successfully implemented the selector, however, my problem is that the selector is only drawing in the background of the image, but I would like to the selector to draw over the entire image. I have seen this problem referenced elsewhere, however, the solution selected by many, setting the drawSelectorOnTop property of the GridView, is not working for me.

The relevant fragment with the relevant adapter code:

public class CollectionsFragment extends Fragment {
    @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container,
                Bundle savedInstanceState) {
             View view = inflater.inflate(R.layout.activity_collections, container, false);
             // Grid view is inside the xml view inflated above
             GridView gridView = (GridView)view.findViewById(R.id.gridview);
             gridView.setDrawSelectorOnTop(true);
             ((GridView) gridView).setAdapter(new CustomGridViewAdapter(getActivity()));
             return view;
        }

        private class CustomGridViewAdapter extends BaseAdapter {
            @Override
            public View getView(int i, View view, ViewGroup viewGroup) {
                View v = view;
                ImageView picture;
                TextView name;

                if(v == null) {
                    v = inflater.inflate(R.layout.collections_item, viewGroup, false);
                    v.setTag(R.id.picture, v.findViewById(R.id.picture));
                    v.setTag(R.id.text, v.findViewById(R.id.text));
                }

                picture = (ImageView)v.getTag(R.id.picture);

                name = (TextView)v.getTag(R.id.text);

                Item item = (Item)getItem(i);
                name.setText(item.name);

                picture.setImageResource(item.drawableId);
                picture.setBackgroundResource(R.drawable.selector);

                return v;
            }
        }
}

And my selector for completeness sake:

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="true" 
      android:drawable="@color/buttonhighlight"/> <!-- pressed state -->
<item android:state_focused="true" 
      android:drawable="@color/buttonhighlight"/> <!-- focused state -->
<item android:drawable="@android:color/transparent"/> <!-- default state --> 
</selector>

Thanks for any help,

lbrendanl
  • 2,626
  • 4
  • 33
  • 54

2 Answers2

15

I think you are mistaken about setDrawSelectorOnTop(boolean). The selector drawable that is being referenced here is GridView's internal selector drawable.

Even in the simplest implementation of GridView, when a grid item is clicked, the blue border is drawn around it. This is because, by default, gridview's own selector is drawn behind the item. If you call setDrawSelectorOnTop(true), the selector (blue) will be drawn over the item.

But setDrawSelectorOnTop(boolean) has nothing to do with the selector you are setting in the adapter. Whether you pass true, or false, the ImageView's selector's behavior won't change.

Solution:

Instead of setting the selector on each ImageView inside the adapter, make the GridView use your selector drawable:

GridView gridView = (GridView)view.findViewById(R.id.gridview);
gridView.setDrawSelectorOnTop(true);

// Make GridView use your custom selector drawable
gridView.setSelector(getResources().getDrawable(R.drawable.selector));

Now, there's no need for:

picture.setBackgroundResource(R.drawable.selector);

Edit:

Although I don't recommend this (obvious overhead), it should work:

@Override
public View getView(int i, View view, ViewGroup viewGroup) {
    View v = view;
    ImageView picture;

    ....
    ....

    LayerDrawable ld = new LayerDrawable(new Drawable[] 

                           // Drawable from item
                           { getResources().getDrawable(item.drawableId), 

                           // Selector
                           getResources().getDrawable(R.drawable.selector)});

    // Set the LayerDrawable
    picture.setImageDrawable(ld);

    // Don't need this
    // picture.setBackgroundResource(R.drawable.selector);

    return v;
}
Vikram
  • 51,313
  • 11
  • 93
  • 122
  • This unfortunately isn't working for me. Now nothing happens even for images that didn't span the whole grid slot. – lbrendanl Dec 02 '13 at 18:18
  • @Zuko, this should work. The only thing I can think of where you might have made a mistake is that you should use `gridView.setSelector(R.color.buttonhighlight));` instead of the example code `gridView.setSelector(getResources().getDrawable(R.drawable.selector));` in this answer exactly. – Joe Dec 02 '13 at 19:40
  • Sorry, my mistake .. I see that there is a selector.xml in your question now. My suggestion to try `R.color.buttonhighlight` as your selector is only good for troubleshooting, I guess :) – Joe Dec 02 '13 at 19:47
  • @Zuko I use this myself and it works as intended. Have you tried following `Joe's` advice? – Vikram Dec 02 '13 at 23:20
  • @Zuko I have added a workaround to my answer. Please see the `Edit` section above. – Vikram Dec 02 '13 at 23:35
2
  1. Try setting the xml attribute android:drawSelectorOnTop in your activity_collections.xml file.

  2. See if placing gridView.setDrawSelectorOnTop(true); after gridView.setAdapter(); helps. Sometimes, the order matters (weird).

  3. If all else fails, you may have to switch GridView to some other view where setDrawSelectorOnTop() is proven to work consistently.

ggorlen
  • 44,755
  • 7
  • 76
  • 106
VJ Vélan Solutions
  • 6,434
  • 5
  • 49
  • 63
  • 1 and 2 unfortunately did not work, do you have any suggestions for a substitute view that has been proven to work consistently? – lbrendanl Dec 02 '13 at 18:19
  • @Zuko Look at the source code of Gallery App - it has a GridView and does exactly what you need. In Gallery App, when you try to select multiple pictures from the Album, the effect you see is similar to what you are trying to achieve, right? That's a GridView they are using there and the source code is open and available. – VJ Vélan Solutions Dec 02 '13 at 22:06