【问题标题】:onClick on ViewPager not triggered未触发 ViewPager 上的 onClick
【发布时间】:2017-05-15 04:39:23
【问题描述】:

我在ViewPager 上设置了一个点击监听器,但从未调用过 onClick 事件。我猜ViewPager 的触摸事件检测有干扰,但我不知道如何解决它...

有人可以帮忙吗?

谢谢

mViewPager.setOnClickListener(new OnClickListener() {
    @Override
    public void onClick(View v) {
        // never called
    }
}); 

【问题讨论】:

  • 您想对 Click 执行的操作可能有助于提供另一种解决方案。
  • 我想要 ListView 的 onItemClickListener() 之类的东西
  • 意味着您想知道在 ViewPager 中点击了哪个项目。这意味着点击了哪个页面位置,对吗?。
  • 实际的列表视图与浏览器不冲突。在 ViewPager 下设置 onClickListeners 也应该可以正常工作。

标签: android android-viewpager


【解决方案1】:

我使用 GestureDetector 解决了类似的问题

将 MotionEvent 发送到 GestureDetector

tapGestureDetector = new GestureDetector(this, new TapGestureListener());

viewPager.setOnTouchListener(new OnTouchListener() {
        public boolean onTouch(View v, MotionEvent event) {
            tapGestureDetector.onTouchEvent(event);
            return false;
        }
});

如果您使用的是兼容性库,您可以将第一行更改为:

tapGestureDetector = new GestureDetectorCompat(this, new TapGestureListener());

您可以在 GestureListener 中处理您的事件:

        class TapGestureListener extends GestureDetector.SimpleOnGestureListener{

         @Override
         public boolean onSingleTapConfirmed(MotionEvent e) {
           // Your Code here
         }
        }

【讨论】:

  • 谢谢,这对我有用,因为我无法扩展 ViewPager。
  • 这就是为此寻找 +1 的内容
  • 如果您希望在单击时触发事件,请考虑 onSingleTapUp 而不是 onSingleTapConfirmed,就像 setOnClickListener 那样。否则该事件将在一段时间后触发,请确保它没有被第二次点击。
  • 非常感谢!完美运行!
【解决方案2】:

我就是这么干的……

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

【讨论】:

  • 我看不出这是一个“丑陋”的解决方案。
【解决方案3】:

确实,viewpager 正在干扰。但是您可以覆盖 viewpager 的方法以使其执行您想要的操作。您需要覆盖 ViewGroup.onInterceptTouchEvent(MotionEvent ev) 方法。

您可以始终返回 false 以允许触摸事件通过。我还建议调用 super.onInterceptTouchEvent(ev) 以允许滑动继续工作。

它传入MotionEvent,因此您可以根据需要检查点击。

希望对您有所帮助。它至少应该让你开始。有问题或其他问题回帖。

编辑:

还要注意 ViewPager 不消耗点击。因此,如果您想捕获点击并可能为自己节省大量工作,您可以轻松地在 viewpager 的任何或所有子级上设置 onclicklistener。

【讨论】:

  • 这是否包含在我的 PagerAdapter 子类中?如何/在哪里写入此覆盖?
  • @CQM 你也可以将它实现为 ViewPager.setOnTouchListener()
  • 对我来说,在ViewPager的OnTouchListener中,它并没有转发ACTION_DOWN事件,只是从ACTION_MOVE开始,拖拽的时候跟着ACTION_UP,点击它什么都不发送,所以似乎覆盖 onInterceptTouchEvent 可能是唯一的解决方案。
【解决方案4】:

我知道这是一个老话题,但我认为这是更容易的解决方案。

ViewPager viewPager = new ViewPager(this);
viewPager.setAdapter(yourPagerAdapter);

// somewhere where you setup your viewPager add this
viewPager.setOnTouchListener(
    new View.OnTouchListener() {
        private boolean moved;

        @Override
        public boolean onTouch(View view, MotionEvent motionEvent) {
            if (motionEvent.getAction() == MotionEvent.ACTION_DOWN) {
                moved = false;
            }
            if (motionEvent.getAction() == MotionEvent.ACTION_MOVE) {
                moved = true;
            }
            if (motionEvent.getAction() == MotionEvent.ACTION_UP) {
                if (!moved) {
                    view.performClick();
                }
            }

            return false;
        }
    }
);

// then you can simply use the standard onClickListener ...
viewPager.setOnClickListener(
    new View.OnClickListener() {

        @Override
        public void onClick(View view) {
            Log.i(LOG, "Dayum!");
        }
    }
);

【讨论】:

  • 如果您的手指移动一点点,Nexus 5 会在点击时发送 ACTION_MOVE。
  • 无法在我的 Nexus 5 (Android 6.0) 上运行,我只是得到一个 ACTION_DOWN,然后是 ACTION_UP。
【解决方案5】:

虽然这不是如何触发 onClick 的直接答案,但它很可能是对相关问题的有用答案 - 在 ViewPager 中捕获点击事件。

只需在您的布局 xml 文件中为分页器项目添加 onClick 属性,然后在您的活动中添加方法。

示例代码:

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);
        // ... 

布局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
    }
  }

【讨论】:

  • 在视图类上定义的 android:onClick 属性的父或祖先上下文中找不到方法 handleAction(View) 收到此错误@Tapirboy
  • @tahsinRupam 方法handleAction(View) 是自己自定义的方法,需要自己实现。
【解决方案6】:

您可以设置ViewPager 的可聚焦性,这样它的孩子就无法接收触摸事件,而是取而代之。

【讨论】:

  • 如果视图寻呼机嵌入在列表视图或滚动视图中,则不工作
【解决方案7】:

确保页面内的意外视图之一没有消耗点击事件。我遇到了一个问题,即图像视图上的 android:clickable 为 true,我无法从其父级获取单击事件。从图像视图中删除该 android:clickable 后,点击事件现在被发送到其父级 (BannerView)。查看示例代码

public ViewPagerAdapter extends PagerAdapter {
...

public Object instantiateItem (ViewGroup container, int position) {

    MyItem item = this.myItems.get(position);

    BannerView bannerView = new BannerView(container.getContext());
    ImageView imageView = (ImageView) bannerView.findViewById(R.id.header_image);

    this.setupClickListener(bannerView, position);

     container.addView(bannerView);
     return bannerView;
}

private void setupClickListener(final BannerView view, final int position) {

    view.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {

               // Page is clicked!
               MyItem item = ViewPagerAdapter.this.myItems.get(position);
               ViewPagerAdapter.this.showNextActivity(view.getContext(), item);               
            }
     });

}

}

【讨论】:

    【解决方案8】:

    执行此操作的正确方法是在您的 Activity 中实现 ViewPager.OnPageChangeListener。这是一个例子:

    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) {
        }
    
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-02-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-12-15
      • 1970-01-01
      相关资源
      最近更新 更多