Android drawSelectorOnTop with GridView
Asked Answered
S

2

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,

Segura answered 27/11, 2013 at 22:24 Comment(0)
S
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;
}
Swinger answered 1/12, 2013 at 7:58 Comment(5)
This unfortunately isn't working for me. Now nothing happens even for images that didn't span the whole grid slot.Segura
@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.Isocracy
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 :)Isocracy
@Zuko I use this myself and it works as intended. Have you tried following Joe's advice?Swinger
@Zuko I have added a workaround to my answer. Please see the Edit section above.Swinger
A
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.

Antidromic answered 1/12, 2013 at 1:41 Comment(2)
1 and 2 unfortunately did not work, do you have any suggestions for a substitute view that has been proven to work consistently?Segura
@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.Arctogaea

© 2022 - 2024 — McMap. All rights reserved.