Kgrover
Kgrover

Reputation: 2116

ViewPager + GridView onItemClick

I have a GridView inside a layout in a ViewPager (I'm not sure if that makes a difference).

inside SampleAdapter for ViewPager{
@Override
        public Object instantiateItem(ViewGroup container, int position) {
            View page = null;
            if (position == 0) {
                page = getLayoutInflater().inflate(R.layout.layoutone,
                        container, false);
            } else {
                page = getLayoutInflater().inflate(R.layout.layouttwo,
                        container, false);
                GridView grid = (GridView) page.findViewById(R.id.gridview);
                grid.setOnItemClickListener(new OnItemClickListener() {

                    @Override
                    public void onItemClick(AdapterView<?> arg0, View arg1,
                            int arg2, long arg3) {

                                  //switch to another activity based on click event

                    }

                });
                grid.setAdapter(new GridItemAdapter(context)); //sets custom gridItemLayout


        container.addView(page);

        return (page);

    }

}

I can view the Grid fine. The custom layout is also working as per my GridAdapter. However, my click event is not being fired. Is it because of the instantiateItem() method call? How can I get around this?

I don't quite understand how Fragments work with ViewPager yet, so if this solution involves switching to a Fragment-based method, it'd be great if someone could elaborate.

Upvotes: 3

Views: 3335

Answers (3)

Leonardo Saganski
Leonardo Saganski

Reputation: 1

Are there any clickable object inside your listView ? If your listView or gridView items contains clickable views (buttons, check boxes etc.) your OnItemClickListener will not be called.

Upvotes: 0

Lalit Poptani
Lalit Poptani

Reputation: 67286

I would insist you to create a seperate Fragment and using getItem(position) of your ViewPager Adapter for sending position and instantiating your Fragment. Inside Fragment you can easily inflate your Layout and use GridView.

 @Override
 public Fragment getItem(int position) {
    return GridFragment.newInstance(position);
}

The current way you are using looks a bit complex for me. So, I would just insist you to try it out. A sample demo is here for the way I am saying.

Upvotes: 2

matt5784
matt5784

Reputation: 3085

So, clicking is a little funny in a ViewPager, because the ViewPager is a little greedy when it comes to catching click/motion events. One solution involves overriding the ViewPager's ViewGroup.onInterceptTouchEvent(MotionEvent ev). However, this isn't always necessary. Specifically, I was unable to set an onClickListener for the pager without doing this, but setting an onClickListener for the views inside the pager works perfectly for me(I've attached a code sample at the end). However, I've never done this with a GridView/onItemClickListener. What you are doing is essentially setting a click listener for views inside a view inside your pager, which is another layer down. As you nest things in Android, touch events become more complicated to manage because of the way the system handles consuming the clicks.

The problem in your situation is that something is consuming your touch event without passing it on to the list item. Essentially, the way Android handles touch events is that when a touch event happens, it passes it to the top-level view's touch event handler function. If the view handles the event, it returns true and the system knows that the event was handled and it is done. If the view doesn't want to handle the event, it returns false and the system passes the event to the next-highest view in the hierarchy. In your case, something (likely the ViewPager or possibly the GridView) is consuming the event before it ever hits your grid item, so the onItemClickListener never gets fired.

As a test, If you can set an onClickListener for the GridView (as in, the entire view) and have it work properly, that means the problem is not with the ViewPager. In this case, you will need to probably implement your own version of GridView and override how it handles touch events to ensure the event makes it to the child items. However, if this doesn't work, you will need to overwrite the ViewPager, as previously mentioned.

(Note: Obviously both of these solutions require a significant amount of time, so before you do either just make sure you have double checked for any simple errors such as putting the Listener on the wrong view, misreading the behavior and thinking it isn't firing when it is, etc.)

For reference, here is a version of an instantiateItem method which works (this is actually still in progress so it's not 100% pretty). The 'menupage' View is a LinearLayout.

public Object instantiateItem(View collection, int position) {
    LayoutInflater inflater = (LayoutInflater) collection.getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    int page = R.layout.menu_page;
    String meal = "";
    switch (position) {
        case 0:
            meal = "Breakfast!";
            break;
        case 1:
            meal = "Lunch!";
            break;
        case 2:
            meal = "Dinner!";
            break;
    }

    View view = inflater.inflate(page, null);
    TextView mealTitle = (TextView) view.findViewById(R.id.meal_title);
    mealTitle.setText(meal);

    ((ViewPager) collection).addView(view, 0);
    final ViewPager pager = (ViewPager)collection;

    View menupage = view.findViewById(R.id.menu_page_ll);
    menupage.setOnClickListener(new View.OnClickListener() {

        @Override
        public void onClick(View v) {
            int page = ((ViewPager) pager).getCurrentItem();
            Intent i = new Intent(getApplicationContext(), Menus.class);
            i.putExtra("page", page);
            startActivity(i);
        }
    });

    return view;
}

Upvotes: 2

Related Questions