Home » Android » java – Android drawSelectorOnTop with GridView

java – Android drawSelectorOnTop with GridView

Posted by: admin June 15, 2020 Leave a comment

Questions:

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,

How to&Answers:

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;
}

Answer:

  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.

HTH