当前位置: 首页 > 知识库问答 >
问题:

Viewpage er2在预览左右滚动不工作

苗学民
2023-03-14

我已经实现了Viewpager2的左右预览,如下图所示。但是滚动只对中间项目(2)有效。不在左(1)和右(3)项目预览上。如何让左右预览滚动工作?

  <androidx.viewpager2.widget.ViewPager2
            android:id="@+id/viewpager"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:orientation="horizontal"
            android:layout_marginTop="@dimen/_5sdp"
            android:paddingStart="@dimen/_50sdp"
            android:paddingEnd="@dimen/_50sdp"
            />

Java代码

    viewpager.setOffscreenPageLimit(3);
    viewpager.setClipToPadding(false);
    viewpager.setClipChildren(false);


    CompositePageTransformer cpt = new CompositePageTransformer();

    cpt.addTransformer(new MarginPageTransformer(10));
    cpt.addTransformer(new ViewPager2.PageTransformer() {
        @Override
        public void transformPage(@NonNull View page, float position) {
            float r = 1 - Math.abs(position);
            page.setScaleY(0.80f + r * 0.20f);
        }
    });

   viewpager.setPageTransformer(cpt);
   viewpager.registerOnPageChangeCallback(new ViewPager2.OnPageChangeCallback() {
        @Override
        public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
            super.onPageScrolled(position, positionOffset, positionOffsetPixels);

            
            if (position == 0) {
                viewpager.setCurrentItem((int) (A1.list.size() / 2));

            }
            
        }
    });

共有2个答案

冉丰茂
2023-03-14

我采用了您的解决方案,使其更加简单,滚动由ViewPager本地处理:

view.findViewById(R.id.nestScrollView).setOnTouchListener(new View.OnTouchListener() {
        final int x_offset = -Tools.dpToPx(30);
        @Override
        public boolean onTouch(View v, MotionEvent motionEvent) {
            motionEvent.offsetLocation(x_offset,0);
            VP_dynamic_area.dispatchTouchEvent(motionEvent);
            return false;
        }
    });

x_offset应该等于我们给ViewPager的填充。我修改了motionEvent,因此触摸将在ViewPager上,而不是在填充区域上。

时经纬
2023-03-14

老实说,我没有找到一个真正的方法来让Viewpager2在左预览和右预览中使用滑动事件,因为Viewpager2类是最终的。但使用NestedScrollview时效果非常好。

由于CmTiger提供了更优化的滚动方式,更新了新的解决方案。我已经测试过了。您可以使用值LEFT_RIGHT = 300从左向右滚动。从dp到pixel获取值。但是,你喜欢。这个新解决方案需要优化。

    float last_x = 0;

    nestedScrollView.setOnTouchListener(new View.OnTouchListener() {
        
        int LEFT_RIGHT = -300;   // your offsets
        int RIGHT_LEFT = 300;

        @Override
        public boolean onTouch(View view, MotionEvent motionEvent) {
            float x = motionEvent.getX();

            if (x > last_x) {
                motionEvent.offsetLocation(LEFT_RIGHT, 0);
            } else {
                motionEvent.offsetLocation(RIGHT_LEFT, 0);
            }

            last_x = x;

            viewpager.dispatchTouchEvent(motionEvent);
            return false;
        }
    });

旧解决方案

          <androidx.core.widget.NestedScrollView
            android:id="@+id/nestedScroll"
            android:layout_width="match_parent"
            android:layout_height="wrap_content">

        <androidx.viewpager2.widget.ViewPager2
            android:id="@+id/viewpager"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="horizontal"
            android:layout_marginTop="@dimen/_5sdp"
            android:paddingStart="@dimen/_50sdp"
            android:paddingEnd="@dimen/_50sdp"
            />
        </androidx.core.widget.NestedScrollView>

只需使用此代码即可使其正常工作。增加速度的int值以提高速度,反之亦然。

  nestedScroll = view.findViewById(R.id.nestedScroll);

    nestedScroll2.setOnTouchListener(new View.OnTouchListener() {
        float start = 0;
        float limit_to_start_moving = 5;
        int speed = 7;
        @Override
        public boolean onTouch(View view, MotionEvent motionEvent) {

            if (motionEvent.getAction() == MotionEvent.ACTION_DOWN) {
                // Touch Starts X  DOWN_X
                start = motionEvent.getX();
            }

            if (motionEvent.getAction() == MotionEvent.ACTION_MOVE) {
                // get position
                float X2 = motionEvent.getX();

                if ((X2 - limit_to_start_moving) > start) {
                    // LEFT & RIGHT DIRECTION
                    if (start < X2)
                        viewpager.fakeDragBy((motionEvent.getXPrecision() * speed));
                    else
                        viewpager.fakeDragBy((motionEvent.getXPrecision() * -speed));
                    start = X2;  // old position

                } else if ((X2 + limit_to_start_moving) < start) {

                    if (start < X2)
                        viewpager.fakeDragBy((motionEvent.getXPrecision() * speed));
                    else
                        viewpager.fakeDragBy((motionEvent.getXPrecision() * -speed));
                    start = X2;

                }
            }

            if (motionEvent.getAction() == MotionEvent.ACTION_UP) {

                if (viewpager.isFakeDragging()) {
                    viewpager.endFakeDrag();
                }

            }

            if (motionEvent.getAction() == MotionEvent.ACTION_CANCEL) {

                if (viewpager.isFakeDragging()) {
                    viewpager.endFakeDrag();
                    if (start > motionEvent.getX()) {
                        viewpager.setCurrentItem(viewpager.getCurrentItem() + 1);
                    } else {
                        viewpager.setCurrentItem(viewpager.getCurrentItem() - 1);
                    }
                }

            }

            return false;
        }
    });

   viewpager.setOnTouchListener(new View.OnTouchListener() {
            float lastValue;
            float value;
            float delta;

            @Override
            public boolean onTouch(View view, MotionEvent event) {
                if (event.getAction() == MotionEvent.ACTION_DOWN) {
                    lastValue = event.getX();
                    viewpager.beginFakeDrag();
                } else if (event.getAction() == MotionEvent.ACTION_MOVE) {
                    value = event.getX();
                    delta = value - lastValue;
                    viewpager.fakeDragBy(delta * 2);
                    lastValue = value;
                } else if (event.getAction() == MotionEvent.ACTION_CANCEL || event.getAction() == MotionEvent.ACTION_UP) {
                    viewpager.endFakeDrag();
                }

                return false;
            }
        });
 类似资料:
  • 我有一个部分,其中左div是固定的,右div是可滚动的,但右div内容滚动,甚至在滚动顶部到达该部分之前。我想要右div滚动只有当它到达div的顶部或底部时(当从底部向上滚动时),但它滚动任何它想要的(不一致-当我快速滚动时,它开始滚动在节的中间,等等)。 当我快速向上或向下滚动时,它甚至会跳过这一节,但我希望它永远不会被跳过。 尝试快速和慢速滚动。卷轴可以随时工作: JSFiddle示例 代码:

  • 本文向大家介绍javascript实现左右控制无缝滚动,包括了javascript实现左右控制无缝滚动的使用技巧和注意事项,需要的朋友参考一下 无缝滚动是项目中经常需要用到的一种特效,网上也有很多的示例代码,这里给大家分享的是一段比较简单实用的,而且兼容性也不错的代码,小伙伴们仔细研究下吧。 html 代码: CSS代码 js:代码 效果是不是非常棒呢。

  • 我有列表视图行的嵌套视图。我也使用水平滚动视图在特定行中水平滚动。但是在一些行中,我希望从右到左滚动功能。我搜索这个,我发现了一些平滑的滚动=“20dp”,但它根本不起作用。 编辑的文本我添加了在我的图像视图点击侦听器,当我点击该图像视图我的水平滚动视图移到结束(右)...我怎么才能使它可能滚动特定的行没有点击侦听器这是我的代码 感谢您的帮助。非常感谢。

  • 问题内容: 假设我有一个,其中将包含一组元素(div),这些元素可能具有不同的高度,但是所有元素的宽度都相同。 目前,我已经通过同位素+砌体实现了这一目标,但是由于某些浏览器已经支持CSS3多列,因此我希望为这些浏览器提供唯一的CSS解决方案,而其余的则使用Javascript。 这是我一直在尝试的CSS: 但是,这使元素的流动从上到下从左到右。我想要的是左右自上而下的流程。这是我想要的示例: 但

  • 本文向大家介绍快速解决jquery.touchSwipe左右滑动和垂直滚动条冲突,包括了快速解决jquery.touchSwipe左右滑动和垂直滚动条冲突的使用技巧和注意事项,需要的朋友参考一下 本文为大家分享了jquery.touchSwipe左右滑动和垂直滚动条冲突问题的解决方法,具体内容如下 正好需要Html5做一个左右可以切换的功能,但是要保留上下滚动条功能。我在移动端使用的jquery.

  • 当滚动距离大于200的时候,禁止继续向右滚动 //禁止继续向右滚动 这里怎么写呢?