I set a click listener on a ViewPager
, but the onClick event is never called. I guess the touch event detection of the ViewPager
is interfering, bu
You can set the focusability of the ViewPager
so that it's children can't receive touch events and it takes them instead.
While this is not an direct answer to how get the onClick triggered, it might very well be an useful answer to the related problem - capturing click events in ViewPager.
Simply add the onClick attribute in your layout xml file for the pager item and add the method in your activity.
Sample code:
PagerAdapter:
class SamplePagerAdapter extends PagerAdapter {
@Override
public Object instantiateItem(ViewGroup container, int position) {
// Inflate a new layout from our resources
View view = getActivity().getLayoutInflater().inflate(R.layout.pager_item,
container, false);
// Add the newly created View to the ViewPager
container.addView(view);
// ...
layout pager_item.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
// usual attributes
>
<ImageButton
// usual attributes
android:onClick="handleAction"
/>
</LinearLayout>
MainActivity:
public class MainActivity extends Activity {
/*
...
*/
public void handleAction(View view) {
// do your stuff
}
}
I solved a similar problem by using a GestureDetector
Sending the MotionEvent to the GestureDetector
tapGestureDetector = new GestureDetector(this, new TapGestureListener());
viewPager.setOnTouchListener(new OnTouchListener() {
public boolean onTouch(View v, MotionEvent event) {
tapGestureDetector.onTouchEvent(event);
return false;
}
});
It you are using the compatibility library, you can change the first line to:
tapGestureDetector = new GestureDetectorCompat(this, new TapGestureListener());
You can handle your Event in the GestureListener:
class TapGestureListener extends GestureDetector.SimpleOnGestureListener{
@Override
public boolean onSingleTapConfirmed(MotionEvent e) {
// Your Code here
}
}
I done like that...
mViewPager.setOnTouchListener(new View.OnTouchListener() {
float oldX = 0, newX = 0, sens = 5;
@Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
oldX = event.getX();
break;
case MotionEvent.ACTION_UP:
newX = event.getX();
if (Math.abs(oldX - newX) < sens) {
itemClicked(mViewPager.getCurrentItem());
return true;
}
oldX = 0;
newX = 0;
break;
}
return false;
}
});
The proper way to do this is to implement ViewPager.OnPageChangeListener in your Activity. Here is an example:
public class MyActivity implements ViewPager.OnPageChangeListener
{
private ViewPager mViewPager;
private int mLastPagePosition = -1;
@Override
protected void onCreate(Bundle savedInstanceState) {
...
mViewPager = (ViewPager) findViewById(R.id.viewpager);
mViewPager.addOnPageChangeListener(this);
...
}
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
if (mLastPagePosition != position) {
// the selected page is changed
mLastPagePosition = position;
}
}
@Override
public void onPageSelected(int position) {
if (mLastPagePosition != position) {
// the selected page is changed
mLastPagePosition = position;
}
}
@Override
public void onPageScrollStateChanged(int state) {
}
}
Indeed the viewpager is interfering. But you can override the methods of the viewpager to make it do what you want. You'll need to override the ViewGroup.onInterceptTouchEvent(MotionEvent ev) method.
You could just always return false to allow the touch events to fall through. I would also recommend calling super.onInterceptTouchEvent(ev) to allow swipes to keep working.
It passes in a MotionEvent, so you could check for clicks with that if you wanted.
Hope that helps. It should at least get you started. Post back with questions or further problems.
EDIT:
Note also that the ViewPager doesn't consume clicks. Therefore you could easily set an onclicklistener on any or all of the children of the viewpager if you wanted to capture clicks and potentially save yourself a lot of work.