ViewPager + GridView onItemClick
I
have a GridView in the layout of ViewPager (I’m not sure if this will be different).
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 see the grid very well. Custom layouts also work according to my GridAdapter. However, my click event is not triggered. Is it because the instantiateItem() method was called? How do I fix this?
I don’t quite understand how Fragments works with ViewPager, so if this solution involves switching to a fragment-based approach, it would be great if someone could elaborate.
Solution
So, clicking in ViewPager is a bit
funny, because ViewPager
is a bit greedy when it comes to capturing click/action events. One solution involves overriding
ViewPager
ViewGroup.onInterceptTouchEvent(MotionEvent ev).However, this is not always necessary. Specifically, I couldn’t set up onClickListener for the pager without doing this, but setting up onClickListener for the View inside the pager worked very well for me (I attached the code example at the end). However, I never did this using GridView
/onItemClickListener. What you’re doing is essentially setting up a click listener for a View within a View within a pager, which is another layer. When you nest things in Android, the management of touch events becomes more complicated due to the way the system handles consuming clicks.
The problem you’re having is that something is consuming your touch event without passing it to the list item. Essentially, Android handles touch events by passing them to the top-level View’s touch event handler when a touch event occurs. If View processed the event, it returns true and the system knows that the event has been processed and has completed. If View does not want to handle the event, it returns false and the event is passed to the next highest View in the hierarchy. In your case, something (maybe a ViewPager
or maybe a GridView
) is consuming the event before it reaches your grid item, so the onItemClickListener is never triggered.
As a test, if you can set up an onClickListener for a GridView
(like the entire View) and have it work, it means that the problem is not with the ViewPager
. In this case, you may need to implement your own version of the GridView
and override how it handles touch events to ensure that the event reaches the children. However, if that doesn’t work, you’ll need to override ViewPager
, as mentioned earlier.
(Note: Obviously, both solutions take a lot of time, so before you execute either solution, make sure you’ve double-checked for any simple errors, such as putting the Listener on the wrong View, misreading the behavior and thinking it doesn’t fire, etc.).
As a reference, here is a
version of the instantiateItem method available (this is actually still a work 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;
}