9

I have a following problem. I have a GridView inside LinearLayout as image below. I want to detect click event when user click at empty space of GridView, in the image, the location that I want is the red area and also inside the green area.

But I have following problems.

  1. If I add onClickListener for GridView: error because Adapter cannot add click event.
  2. If I add onItemClickListener for GridView: I just can detect where exist items (in the image is the white box)
  3. If I add onClickListener for LinearLayout I just can detect click event on green area, not red area.

So how can I fix above problem.

@Edit: my layout looks like:

<LinearLayout>
  <GridView
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"/>
</LinearLayout>

Thanks :)

enter image description here

hqt
  • 29,632
  • 51
  • 171
  • 250
  • Possible duplicate of: http://stackoverflow.com/questions/4415528/how-to-pass-the-onclick-event-to-its-parent-on-android – selbie Sep 08 '14 at 18:00

4 Answers4

11

Since the parent LinearLayout can be assigned its own OnClickListener, the issue is only how to detect a click within the GridView that occurs outside of its child Views. You can subclass GridView and override the dispatchTouchEvent() method to accomplish this. Using the pointToPosition() method, we can determine if a touch event occurs outside of the child Views, and use an interface to notify a listener if it is. In the following example, the OnNoItemClickListener interface provides that functionality.

public class TouchyGridView extends GridView
{
    // Depending on how you're creating this View,
    // you might need to specify additional constructors.
    public TouchyGridView(Context context, AttributeSet attrs)
    {
        super(context, attrs);
    }

    private OnNoItemClickListener listener;
    public interface OnNoItemClickListener
    {
        public void onNoItemClick();
    }

    public void setOnNoItemClickListener(OnNoItemClickListener listener)
    {
        this.listener = listener;
    }

    @Override
    public boolean dispatchTouchEvent(MotionEvent event)
    {
        // The pointToPosition() method returns -1 if the touch event
        // occurs outside of a child View.
        // Change the MotionEvent action as needed. Here we use ACTION_DOWN
        // as a simple, naive indication of a click.
        if (pointToPosition((int) event.getX(), (int) event.getY()) == -1
            && event.getAction() == MotionEvent.ACTION_DOWN)
        {
            if (listener != null)
            {
                listener.onNoItemClick();
            }
        }
        return super.dispatchTouchEvent(event);
    }
}
Mike M.
  • 38,532
  • 8
  • 99
  • 95
3

Declare your GridView not clickable / focusable by using

android:clickable="false" and android:focusable="false"

or

v.setClickable(false) and v.setFocusable(false)

The click events should be dispatched to the GridView's parent now.

Note: In order to achieve this, you have to add click to its direct parent. or set android:clickable="false" and android:focusable="false" to its direct parent to pass listener to further parent.

thnx to SIYB's answer https://stackoverflow.com/a/18959830/3818437

Community
  • 1
  • 1
mhdjazmati
  • 4,152
  • 1
  • 26
  • 37
1

U can just set both OnItemClickListener and OnTouchListener and
Handle Grid View empty area clicks inside OnTouchListener.

    gridViewVar.setOnItemClickListener(new AdapterView.OnItemClickListener()
    {
        public void onItemClick(AdapterView<?> parent, View VyuIdxPsgVar,
                int IdxPsgVal, long id)
        {
            // Code Something todo on item clicked
        }
    });
    gridViewVar.setOnTouchListener(new View.OnTouchListener()
    {
        @Override
        public boolean onTouch(View v, MotionEvent event)
        {
            if (gridViewVar.pointToPosition((int) event.getX(), (int) event.getY()) == -1
                    && event.getAction() == MotionEvent.ACTION_DOWN)
            {
                // Code Something todo on empty space
            }
            return false;
        }
    });
Sujay U N
  • 4,974
  • 11
  • 52
  • 88
0

Looks like you put onClickListener on wrong layout (you put it only on inner/green area layout and not on global RelativeLayout wich can catch clicks from grid and linear layouts both).

Vitaliy A
  • 3,651
  • 1
  • 32
  • 34
  • in fact. linear layout is a container of gridview. but maybe because grid view is above, so at red area, clicking event cannot come into linear layout. :( – hqt Sep 08 '14 at 16:26
  • I do not think that this is a reason. But you can create one single onClickListener and add it to Linear and Grid layouts both. – Vitaliy A Sep 08 '14 at 16:36
  • as three tests above, no test cases can detect red area section. So, I think add click listener for both layout will not work – hqt Sep 08 '14 at 16:39
  • Just set to Grid setOnTouchListener, do not forget to return true/false according to app logic. OnTouchListener will handle every touch events on this layout. – Vitaliy A Sep 09 '14 at 10:51