【问题标题】:Android: RecyclerView within vertical viewpagerAndroid:垂直viewpager中的RecyclerView
【发布时间】:2016-07-23 16:29:02
【问题描述】:

我想在垂直视图页面中实现一个回收视图。我当前的布局如下所示

VerticalViewpager
- Fragment1
    - ImageView
- Fragment2 
    - RecyclerView

如果我从 Fragment1 滑动到 Fragment2,一切正常。我可以在回收站视图中上下滚动。如果我尝试滑动/滚动回 Fragment1,就会出现问题。

如果用户已经滚动到recyclerview的顶部,我想将下一个“Up”-Scroll事件转发到垂直viewpager。我尝试过覆盖onInterceptTouchEvent 方法,但不幸的是仍然没有成功。有什么想法吗?感谢您的帮助:)

【问题讨论】:

  • 嗨!我需要做同样的事情,运气好吗?
  • 嗨@Caique,很遗憾,没有适用于我们所有情况的解决方案。印度先生的建议对我们很有帮助,但正如我在他的建议下方的评论中已经提到的那样,这个解决方案并非每次都有效。
  • 感谢您的回答。我所做的是:我覆盖了 recyclerview 的 onTouch,从 ACTION_DOWN、ACTION_MOVE 和 ACTION_UP 中获得了速度,如果速度 > 500(以一定的速度上升),我在 viewpager 上返回一个位置。它工作得很好。我将发布代码作为答案,也许可以帮助你
  • 那真是太好了。一旦你发布它,我会尝试你的解决方案:)

标签: android scroll android-viewpager android-recyclerview vertical-scrolling


【解决方案1】:

您需要禁用scroll。尝试使用recyclerView.setNestedScrollingEnabled(false);

【讨论】:

  • 您好,谢谢您的回答。我试过了,它可以工作......有时:D 如果我到达回收站视图的顶部,我必须滚动至少四到五次,直到 VerticalViewpager 收到事件并滚动回 Fragment1。知道是什么导致了这种行为吗?
【解决方案2】:

1) 需要使用23.2.0(或)以上的支持库 2) 并且 recyclerView 的高度将是 wrap_content。 3) recyclerView.setNestedScrollingEnabled(false)

但是这样做回收器模式不起作用。 (即所有视图将一次加载,因为 wrap_content 需要完整 recyclerView 的高度,因此它将一次绘制所有回收器视图。不会回收任何视图)。除非确实需要,否则尽量不要使用此模式工具。

【讨论】:

    【解决方案3】:
    recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
                    @Override
                    public void onScrolled (RecyclerView recyclerView,int dx, int dy) {
                    int topRowVerticalPosition = (recyclerView == null || recyclerView.getChildCount() == 0) ? 0 : recyclerView.getChildAt(0).getTop();
                    if (topRowVerticalPosition >= 0) {
                        //top position
                    }
                }
                    @Override
                    public void onScrollStateChanged (RecyclerView recyclerView,int newState) {
                    super.onScrollStateChanged(recyclerView, newState);
                }
                });
    

    通过使用此代码,您可以确定用户是否处于顶部位置。在该位置,您可以使视图寻呼机移动到您想要的位置。

    【讨论】:

    • 如果用户已经在回收站视图的顶部位置并尝试向上滚动以触发 viewpager,则检测不起作用。
    • @AlexanderHoffmann:: 尝试将 int topRowVerticalPosition = 0; 声明为 public。
    • 我无法在 onScroll 方法中将变量设置为 public。无论如何,这都有意义,不是吗?
    • @AlexanderHoffmann:: 你也可以检查这个 recyclerView.getChildCount() == 0 来找到孩子的数量。
    【解决方案4】:

    如果您可以从 RecyclerView 访问 VerticalViewPager,则可以扩展 RecyclerView 并检查 canScrollVertically(-1) 并将触摸事件转发到 viewpager

    【讨论】:

      【解决方案5】:

      你需要在父滚动视图中禁止嵌套滚动 我有这个新工具,你可以试试下面的链接https://github.com/liuxiaocong/VerticalViewpage

      【讨论】:

        【解决方案6】:

        我遇到了同样的问题。 Mr.India 的回答很有帮助,但正如您所说,它只在某些时候有效。

        我做的是

        recyclerView.setOnTouchListener(new View.OnTouchListener() {
                    public float speed;
                    public VelocityTracker mVelocityTracker;
        
                    @Override
                    public boolean onTouch(View v, MotionEvent event) {
                        int index = event.getActionIndex();
                        int action = event.getActionMasked();
                        int pointerId = event.getPointerId(index);
        
                        switch (action) {
        
                            case MotionEvent.ACTION_DOWN:
                                if(mVelocityTracker == null) {
                                    mVelocityTracker = VelocityTracker.obtain();
                                }
                                else {
                                    mVelocityTracker.clear();
                                }
                                mVelocityTracker.addMovement(event);
                                break;
                            case MotionEvent.ACTION_MOVE:
                                if(mVelocityTracker != null) {
                                    mVelocityTracker.addMovement(event);
                                    mVelocityTracker.computeCurrentVelocity(1000);
                                    speed = VelocityTrackerCompat.getYVelocity(mVelocityTracker, pointerId);
                                }
                                break;
                            case MotionEvent.ACTION_UP:
                                int topRowVerticalPosition = (recyclerView == null || recyclerView.getChildCount() == 0) ? 0 : recyclerView.getChildAt(0).getTop();
                                if(speed > 500 && topRowVerticalPosition >= 0) {
                                    ReaderFragmentParent parent = (ReaderFragmentParent) getActivity();
                                    ReaderPager pager = parent.getPager();
                                    if(pager != null) {
                                        pager.setCurrentItem(pager.getCurrentItem()-1);
                                    }
        
                                }
                                return false;
                            case MotionEvent.ACTION_CANCEL:
                                mVelocityTracker.recycle();
                                break;
                        }
        
        
                        return false;
                    }
                });
        

        在 ACTION_UP 上,我验证速度是否 > 500,这意味着它正在以考虑的速度上升,而 topRowVerticalPosition 意味着它位于 recyclerview 的顶部。然后我将 ViewPager 和 setCurrentItem 设置为上一个项目。

        这有点脏,但这是我发现在 Vertical ViewPager 上看起来像在页面之间滚动的唯一方法

        【讨论】:

          【解决方案7】:
          mRecyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
                      @Override
                      public void onScrolled (RecyclerView recyclerView,int dx, int dy) {
          
                      }
                      @Override
                      public void onScrollStateChanged (RecyclerView recyclerView,int newState) {
                          super.onScrollStateChanged(recyclerView, newState);
          
                          if (!mRecyclerView.canScrollVertically(-1) && newState == 0) {
          
                              Log.e("canScrollVertically", mRecyclerView.canScrollVertically(-1)+"");
          
                              verticalViewPager.setCurrentItem(0, true);
                          }
                      }
                  });
          

          【讨论】:

            【解决方案8】:

            我建议先迁移到 ViewPager2,因为它原生允许垂直滚动,然后使用官方documentation 提供的解决方案来支持嵌套的可滚​​动元素。

            基本上,您需要将NestedScrollableHost 添加到您的项目中,然后用它包装您的 RecyclerView,如下所示:

                <NestedScrollableHost
                        android:layout_width="match_parent"
                        android:layout_height="match_parent">
            
                    <androidx.recyclerview.widget.RecyclerView
                            android:id="@+id/my_recycler_view"
                            android:layout_width="match_parent"
                            android:layout_height="match_parent"
                            android:orientation="vertical" />
            
                </NestedScrollableHost>
            

            请注意,此解决方案仅适用于您提供的布局,其中 RecyclerView 将是您的 ViewPager 屏幕之一的直接子级。此解决方案不适用于嵌套在主 RecyclerView 中的其他 RecyclerView。

            【讨论】:

              猜你喜欢
              • 2015-01-22
              • 2017-05-02
              • 2016-01-20
              • 1970-01-01
              • 1970-01-01
              • 2016-02-01
              • 1970-01-01
              • 2021-09-12
              • 2016-05-20
              相关资源
              最近更新 更多