Android:垂直ViewPager [关闭]


130

有没有一种方法可以使ViewPager水平滚动而不是垂直滚动?


1
垂直ViewPager有一个新的非官方开源实现:公告: plus.google.com/107777704046743444096/posts/1FTJfrvnY8w 代码: github.com/LambergaR/VerticalViewPager
Vasily Sochinsky 2013年

Antoine Merle的垂直视图传呼机实现:github.com/castorflex/VerticalViewPager
micnoy 2014年

有一个基于19支持库的新实现:github.com/castorflex/VerticalViewPager
Vasily Sochinsky 2014年

尽管名称相似,但这与github.com/castorflex/VerticalViewPager不同
Flimm

1
有一个名为ViewPager2的控件,请在此处检查以了解演示stackoverflow.com/a/54643817/7666442
Nilesh Rathod

Answers:


227

您可以使用ViewPager.PageTransformer来产生Vertical的错觉ViewPager。为了实现垂直滚动而不是水平拖动的滚动,您必须覆盖ViewPager的默认触摸事件并MotionEvent在处理它们之前交换s 的坐标,例如:

/**
 * Uses a combination of a PageTransformer and swapping X & Y coordinates
 * of touch events to create the illusion of a vertically scrolling ViewPager. 
 * 
 * Requires API 11+
 * 
 */
public class VerticalViewPager extends ViewPager {

    public VerticalViewPager(Context context) {
        super(context);
        init();
    }

    public VerticalViewPager(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    private void init() {
        // The majority of the magic happens here
        setPageTransformer(true, new VerticalPageTransformer());
        // The easiest way to get rid of the overscroll drawing that happens on the left and right
        setOverScrollMode(OVER_SCROLL_NEVER);
    }

    private class VerticalPageTransformer implements ViewPager.PageTransformer {

        @Override
        public void transformPage(View view, float position) {

            if (position < -1) { // [-Infinity,-1)
                // This page is way off-screen to the left.
                view.setAlpha(0);

            } else if (position <= 1) { // [-1,1]
                view.setAlpha(1);

                // Counteract the default slide transition
                view.setTranslationX(view.getWidth() * -position);

                //set Y position to swipe in from top
                float yPosition = position * view.getHeight();
                view.setTranslationY(yPosition);

            } else { // (1,+Infinity]
                // This page is way off-screen to the right.
                view.setAlpha(0);
            }
        }
    }

    /**
     * Swaps the X and Y coordinates of your touch event.
     */
    private MotionEvent swapXY(MotionEvent ev) {
        float width = getWidth();
        float height = getHeight();

        float newX = (ev.getY() / height) * width;
        float newY = (ev.getX() / width) * height;

        ev.setLocation(newX, newY);

        return ev;
    }

    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev){
        boolean intercepted = super.onInterceptTouchEvent(swapXY(ev));
        swapXY(ev); // return touch coordinates to original reference frame for any child views
        return intercepted;
    }

    @Override
    public boolean onTouchEvent(MotionEvent ev) {
        return super.onTouchEvent(swapXY(ev));
    }

}

当然,您可以根据需要调整这些设置。最终看起来像这样:

VerticalViewPager演示


3
@Der Golem如何为此使用布局?
bShah 2014年

确切的问题是什么?顺便说一句,我没有发布答案,只是添加了引用的图像。
Phantômaxx

1
@Brett在此示例中,我想左右滑动执行一些操作。怎么做
Prabs

1
@Brett可以正常工作,过渡在垂直进行。但是问题是我必须向右/向左滑动以进行过渡,并且在滑动顶部/底部时不会发生过渡。
卡兰·库拉纳

2
@Brett我正在使用您的解决方案。但现在我在ororid馅饼设备中遇到了刷卡问题。是否有人面临同样的问题?
吉桑

20

垂直ViewPager

这里的其他答案似乎都与他们有关。甚至推荐的开源项目也没有将最近的请求请求与错误修复合并。然后我VerticalViewPager从Google 找到一个他们使用了DeskClock应用程序的应用程序。我相信使用Google的实现比这里提供的其他答案要多得多。(Google的版本与当前投票最多的答案相似,但更为详尽。)

完整的例子

该示例与我的Basic ViewPager示例几乎完全相同,但需要进行一些小的更改以使用VerticalViewPager该类。

在此处输入图片说明

XML格式

为主要活动和每个页面(片段)添加xml布局。请注意,我们使用的VerticalViewPager不是标准ViewPager。我将在下面包含该代码。

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.example.verticalviewpager.MainActivity">

    <com.example.myapp.VerticalViewPager
        android:id="@+id/viewpager"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

</RelativeLayout>

fragment_one.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
                android:layout_width="match_parent"
                android:layout_height="match_parent" >

    <TextView
        android:id="@+id/textview"
        android:textSize="30sp"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true" />

</RelativeLayout>

的代码VerticalViewPager不是我的。它只是Google源代码的精简版本(无注释)。签出最新版本。那里的评论也有助于理解正在发生的事情。

VerticalViewPager.java

import android.support.v4.view.ViewPager;    

public class VerticalViewPager extends ViewPager {

    public VerticalViewPager(Context context) {
        this(context, null);
    }

    public VerticalViewPager(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    @Override
    public boolean canScrollHorizontally(int direction) {
        return false;
    }

    @Override
    public boolean canScrollVertically(int direction) {
        return super.canScrollHorizontally(direction);
    }

    private void init() {
        setPageTransformer(true, new VerticalPageTransformer());
        setOverScrollMode(View.OVER_SCROLL_NEVER);
    }

    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        final boolean toIntercept = super.onInterceptTouchEvent(flipXY(ev));
        flipXY(ev);
        return toIntercept;
    }

    @Override
    public boolean onTouchEvent(MotionEvent ev) {
        final boolean toHandle = super.onTouchEvent(flipXY(ev));
        flipXY(ev);
        return toHandle;
    }

    private MotionEvent flipXY(MotionEvent ev) {
        final float width = getWidth();
        final float height = getHeight();
        final float x = (ev.getY() / height) * width;
        final float y = (ev.getX() / width) * height;
        ev.setLocation(x, y);
        return ev;
    }

    private static final class VerticalPageTransformer implements ViewPager.PageTransformer {
        @Override
        public void transformPage(View view, float position) {
            final int pageWidth = view.getWidth();
            final int pageHeight = view.getHeight();
            if (position < -1) {
                view.setAlpha(0);
            } else if (position <= 1) {
                view.setAlpha(1);
                view.setTranslationX(pageWidth * -position);
                float yPosition = position * pageHeight;
                view.setTranslationY(yPosition);
            } else {
                view.setAlpha(0);
            }
        }
    }
}

MainActivity.java

我只换出VerticalViewPagerViewPager

import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;
import android.support.v4.view.ViewPager;

public class MainActivity extends AppCompatActivity {

    static final int NUMBER_OF_PAGES = 2;

    MyAdapter mAdapter;
    VerticalViewPager mPager;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        mAdapter = new MyAdapter(getSupportFragmentManager());
        mPager = findViewById(R.id.viewpager);
        mPager.setAdapter(mAdapter);
    }

    public static class MyAdapter extends FragmentPagerAdapter {
        public MyAdapter(FragmentManager fm) {
            super(fm);
        }

        @Override
        public int getCount() {
            return NUMBER_OF_PAGES;
        }

        @Override
        public Fragment getItem(int position) {

            switch (position) {
                case 0:
                    return FragmentOne.newInstance(0, Color.WHITE);
                case 1:
                    // return a different Fragment class here
                    // if you want want a completely different layout
                    return FragmentOne.newInstance(1, Color.CYAN);
                default:
                    return null;
            }
        }
    }

    public static class FragmentOne extends Fragment {

        private static final String MY_NUM_KEY = "num";
        private static final String MY_COLOR_KEY = "color";

        private int mNum;
        private int mColor;

        // You can modify the parameters to pass in whatever you want
        static FragmentOne newInstance(int num, int color) {
            FragmentOne f = new FragmentOne();
            Bundle args = new Bundle();
            args.putInt(MY_NUM_KEY, num);
            args.putInt(MY_COLOR_KEY, color);
            f.setArguments(args);
            return f;
        }

        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            mNum = getArguments() != null ? getArguments().getInt(MY_NUM_KEY) : 0;
            mColor = getArguments() != null ? getArguments().getInt(MY_COLOR_KEY) : Color.BLACK;
        }

        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container,
                                 Bundle savedInstanceState) {
            View v = inflater.inflate(R.layout.fragment_one, container, false);
            v.setBackgroundColor(mColor);
            TextView textView = v.findViewById(R.id.textview);
            textView.setText("Page " + mNum);
            return v;
        }
    }
}

已完成

您应该能够运行该应用程序,并在上面的动画中查看结果。

也可以看看


3
代码可以正常工作,只需要1个小帮助。在当前代码中,我们需要从下往上滑动才能获得下一页,但是我希望即使是很小的滑动也可以得到下一页。
AMIT

20

我有一个适用于我的解决方案,只需两个步骤。

  1. onInstantiateItem()PagerAdapter,创建视图并将其旋转-90:

    view.setRotation(-90f)

    如果您使用FragmentPagerAdapter,则:

    objFragment.getView().setRotation(-90)
  2. ViewPager视图旋转90度:

    objViewPager.setRotation(90)

至少对于我的要求而言,它像魅力一样起作用。


4
此解决方案有效,但您仍然必须水平滑动,而viewPager现在垂直滚动
leochab 2014年

@库莱我不知道该怎么办,根据我的理解,您可以解释一下吗,因为我们有公共对象InstantiateItem(ViewGroup container,int position),在这里我们需要做container.setRotation(-90f);
瓦伦2014年

1
这样做就像一种魅力!Althoug顶部和底部的视图都被切掉了,我不知道为什么:-/
NivaldoBondança2014年

2
它适用于正方形图像而不适用于矩形图像。旋转矩形时尺寸会出错。
古来2014年

1
我不确定谁赞成这个答案。这不是VerticalViewPager,这是旋转90度的ViewPager,手势和过渡恰好相反。而且它根本不是自然的
droidev '19

14

对于正在努力使垂直ViewPager在水平内部工作的人,只需执行以下操作:

垂直ViewPager

public class VerticalViewPager extends ViewPager {
    public VerticalViewPager(Context context) {
        super(context);
        init();
    }

    public VerticalViewPager(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    private void init() {
        setPageTransformer(true, new VerticalPageTransformer());
        setOverScrollMode(OVER_SCROLL_NEVER);
    }

    private class VerticalPageTransformer implements ViewPager.PageTransformer {

        @Override
        public void transformPage(View view, float position) {

            if (position < -1) {
                view.setAlpha(0);
            } else if (position <= 1) {
                view.setAlpha(1);

                view.setTranslationX(view.getWidth() * -position);

                float yPosition = position * view.getHeight();
                view.setTranslationY(yPosition);
            } else {
                view.setAlpha(0);
            }
        }
    }

    private MotionEvent swapXY(MotionEvent ev) {
        float width = getWidth();
        float height = getHeight();

        float newX = (ev.getY() / height) * width;
        float newY = (ev.getX() / width) * height;

        ev.setLocation(newX, newY);

        return ev;
    }

    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        boolean intercepted = super.onInterceptTouchEvent(swapXY(ev));
        swapXY(ev);
        return intercepted;
    }

    @Override
    public boolean onTouchEvent(MotionEvent ev) {
        return super.onTouchEvent(swapXY(ev));
    }

}

水平ViewPager

public class HorizontalViewPager extends ViewPager {
    private GestureDetector xScrollDetector;

    public HorizontalViewPager(Context context) {
        super(context);
    }

    public HorizontalViewPager(Context context, AttributeSet attrs) {
        super(context, attrs);
        xScrollDetector = new GestureDetector(getContext(), new XScrollDetector());
    }

    class XScrollDetector extends GestureDetector.SimpleOnGestureListener {
        @Override
        public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
            return Math.abs(distanceX) > Math.abs(distanceY);
        }
    }

    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        if (xScrollDetector.onTouchEvent(ev)) {
            super.onInterceptTouchEvent(ev);
            return true;
        }

        return super.onInterceptTouchEvent(ev);
    }

}

如何将此水平和垂直视图寻呼机添加到视图中?
user1810931


如何在视图中实现上述“水平和垂直”视图寻呼机类?代码段帮助
user1810931

ViewPager已经在查看,我不明白您的要求。
Divers

我正在使用一个名为“材料日历视图”的库(github.com/prolificinteractive/material-calendarview),它已经具有水平viewpager,并且我想在其中添加垂直viewpager。
user1810931

8

略微扩展答案有助于我达到要求(“垂直视图传呼机”以类似“ 短裤”(60个单词的新闻)中的内容进行动画处理)

public class VerticalViewPager extends ViewPager {

public VerticalViewPager(Context context) {
    super(context);
    init();
}

public VerticalViewPager(Context context, AttributeSet attrs) {
    super(context, attrs);
    init();
}

private void init() {
    // The majority of the magic happens here
    setPageTransformer(true, new VerticalPageTransformer());
    // The easiest way to get rid of the overscroll drawing that happens on the left and right
    setOverScrollMode(OVER_SCROLL_NEVER);
}

private class VerticalPageTransformer implements ViewPager.PageTransformer {
 private static final float MIN_SCALE = 0.75f;
    @Override
    public void transformPage(View view, float position) {

        if (position < -1) { // [-Infinity,-1)
            // This page is way off-screen to the left.
            view.setAlpha(0);

        }  else if (position <= 0) { // [-1,0]
            // Use the default slide transition when moving to the left page
            view.setAlpha(1);
            // Counteract the default slide transition
            view.setTranslationX(view.getWidth() * -position);

            //set Y position to swipe in from top
            float yPosition = position * view.getHeight();
            view.setTranslationY(yPosition);
            view.setScaleX(1);
            view.setScaleY(1);

        } else if (position <= 1) { // [0,1]
            view.setAlpha(1);

            // Counteract the default slide transition
            view.setTranslationX(view.getWidth() * -position);


            // Scale the page down (between MIN_SCALE and 1)
            float scaleFactor = MIN_SCALE
                    + (1 - MIN_SCALE) * (1 - Math.abs(position));
            view.setScaleX(scaleFactor);
            view.setScaleY(scaleFactor);

        } else { // (1,+Infinity]
            // This page is way off-screen to the right.
            view.setAlpha(0);
        }

    }

}

/**
 * Swaps the X and Y coordinates of your touch event.
 */
private MotionEvent swapXY(MotionEvent ev) {
    float width = getWidth();
    float height = getHeight();

    float newX = (ev.getY() / height) * width;
    float newY = (ev.getX() / width) * height;

    ev.setLocation(newX, newY);

    return ev;
}

@Override
public boolean onInterceptTouchEvent(MotionEvent ev){
    boolean intercepted = super.onInterceptTouchEvent(swapXY(ev));
    swapXY(ev); // return touch coordinates to original reference frame for any child views
    return intercepted;
}

@Override
public boolean onTouchEvent(MotionEvent ev) {
    return super.onTouchEvent(swapXY(ev));
}
}

我希望这可能对其他人有帮助。


1
MIN_SCALE的理想值?
divyenduz

您是否发现快速刷卡的问题过渡并不顺利
Praneeth

到底为什么有人会快速刷卡?
Amrut Bidri '16

只需澄清一下即可:此解决方案更改了动画,使新页面不是从下面而是从旧页面后面。因此,基本上,您没有将页面并排放置,而是将一叠页面并排放置。因此,此解决方案可能不是原始问题要解决的问题。
本杰明·巴斯马奇

4

有一些开源项目声称可以做到这一点。他们来了:

它们的作者已将其标记为已弃用:

还有一件事情:


3

2
需要记住的一点是,该功能DirectionalViewPager已经有一段时间没有更新了,因此缺少ViewPager了支持库中的一些新功能;即 setPageMargin(int)。通常,它应该完成这项工作。如果不是这样,获取源代码ViewPager并换出所有x / y和width / height逻辑也不太麻烦。
MH。

我已经考虑过了,DirectionalViewPager但是,正如MH所说,它尚未更新(其开发者认为它已弃用)!令人难以置信的是,Android开发人员没有向社区提供垂直的ViewPager,而只是水平的。我更新到Android,开发我的垂直ViewPager换出X / Y也不是那么容易的,我..我宁愿一个已经构建的解决方案。不管怎么样,谢谢你
user1709805

2
嗨,您是否成功进行了垂直viewpager?thansk
Paul

3

由于设备显示为矩形,因此对@Brett@ Salman666的答案进行了改进,可以将坐标(X,Y)正确转换为(Y,X)。

...

/**
 * Swaps the X and Y coordinates of your touch event
 */
@Override
public boolean onTouchEvent(MotionEvent ev) {
    return super.onTouchEvent(swapXY(ev));
}

@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
    return super.onInterceptTouchEvent(swapXY(ev));
}

private MotionEvent swapXY(MotionEvent ev) {

    //Get display dimensions
    float displayWidth=this.getWidth();
    float displayHeight=this.getHeight();

    //Get current touch position
    float posX=ev.getX();
    float posY=ev.getY();

    //Transform (X,Y) into (Y,X) taking display dimensions into account
    float newPosX=(posY/displayHeight)*displayWidth;
    float newPosY=(1-posX/displayWidth)*displayHeight;

    //swap the x and y coords of the touch event
    ev.setLocation(newPosX, newPosY);

    return ev;
}

...

但是,仍然需要采取一些措施来改善触摸屏的响应能力。该问题可能与@msdark对@​​ Salman666的答案发表了评论。


通过始终返回true,我进行了一些改进,onInterceptTouchEvent并且还修改了键绑定,因此使用DPAD可以触发UP / DOWN(而不是左/右)滚动:gist.github.com/zevektor/fbacf4f4f6c39fd6e409
Vektor88

@ Vektor88始终返回true将阻止内部视图接收触摸事件..最佳解决方案如brett答案..
Mohammad Zekrallah

2
import android.content.Context;
import android.support.v4.view.ViewPager;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;

public class VerticalViewPager extends ViewPager {

    public VerticalViewPager(Context context) {
        super(context);
        init();
    }


    public VerticalViewPager(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }
    private void init() {

        setPageTransformer(true, new VerticalPageTransformer());

        setOverScrollMode(OVER_SCROLL_NEVER);
    }

    private class VerticalPageTransformer implements PageTransformer {

        @Override
        public void transformPage(View view, float position) {
            int pageWidth = view.getWidth();
            int pageHeight = view.getHeight();

            if (position < -1) {

                view.setAlpha(0);

            } else if (position <= 1) {
                view.setAlpha(1);


                view.setTranslationX(pageWidth * -position);


                float yPosition = position * pageHeight;
                view.setTranslationY(yPosition);

            } else {

                view.setAlpha(0);
            }
        }
    }
        @Override
    public boolean onTouchEvent(MotionEvent ev) {

        ev.setLocation(ev.getY(), ev.getX());

        return super.onTouchEvent(ev);
    }
    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        ev.setLocation(ev.getY(), ev.getX());
        return super.onInterceptTouchEvent(ev);
    }
}

1
这工作得很好,但是我丢失了元素上的touchEvent或左/挥动事件……
matiasfha 2014年

0

实际上,Android源码中已经有一个。我已经对其进行了修改以使其更好地工作:

package com.crnlgcs.sdk.widgets;



import android.content.Context;
import android.support.v4.view.ViewConfigurationCompat;
import android.support.v4.view.ViewPager;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewConfiguration;
import android.view.ViewParent;

public class VerticalViewPager extends ViewPager {
    private static final String TAG = "VerticalViewPager";
    private static final boolean DEBUG = true;

    private float mLastMotionX;
    private float mLastMotionY;
    private float mTouchSlop;
    private boolean mVerticalDrag;
    private boolean mHorizontalDrag;

    // Vertical transit page transformer
    private final ViewPager.PageTransformer mPageTransformer = new ViewPager.PageTransformer() {
        @Override
        public void transformPage(View view, float position) {
            final int pageWidth = view.getWidth();
            final int pageHeight = view.getHeight();
            if (position < -1) {
                // This page is way off-screen to the left.
                view.setAlpha(0);
            } else if (position <= 1) {
                view.setAlpha(1);
                // Counteract the default slide transition
                view.setTranslationX(pageWidth * -position);
                // set Y position to swipe in from top
                float yPosition = position * pageHeight;
                view.setTranslationY(yPosition);
            } else {
                // This page is way off-screen to the right.
                view.setAlpha(0);
            }
        }
    };

    public VerticalViewPager(Context context) {
        super(context, null);
    }

    public VerticalViewPager(Context context, AttributeSet attrs) {
        super(context, attrs);
        final ViewConfiguration configuration = ViewConfiguration.get(context);
        mTouchSlop = ViewConfigurationCompat.getScaledPagingTouchSlop(configuration);
        init();
    }

    private void init() {
        // Make page transit vertical
        setPageTransformer(true, mPageTransformer);
        // Get rid of the overscroll drawing that happens on the left and right (the ripple)
        setOverScrollMode(View.OVER_SCROLL_NEVER);
    }

    @Override
    public boolean onTouchEvent(MotionEvent ev) {

        final float x = ev.getX();
        final float y = ev.getY();

        if (DEBUG) Log.v(TAG, "onTouchEvent " + x + ", " + y);

        switch (ev.getAction()) {
            case MotionEvent.ACTION_DOWN: {
                mLastMotionX = x;
                mLastMotionY = y;
                if (!super.onTouchEvent(ev))
                    return false;
                return verticalDrag(ev);
            }
            case MotionEvent.ACTION_MOVE: {
                final float xDiff = Math.abs(x - mLastMotionX);
                final float yDiff = Math.abs(y - mLastMotionY);
                if (!mHorizontalDrag && !mVerticalDrag) {
                    if (xDiff > mTouchSlop && xDiff > yDiff) { // Swiping left and right
                        mHorizontalDrag = true;
                    } else if (yDiff > mTouchSlop && yDiff > xDiff) { //Swiping up and down
                        mVerticalDrag = true;
                    }
                }
                if (mHorizontalDrag) {
                    return super.onTouchEvent(ev);
                } else if (mVerticalDrag) {
                    return verticalDrag(ev);
                }
            }
            case MotionEvent.ACTION_UP: {
                if (mHorizontalDrag) {
                    mHorizontalDrag = false;
                    return super.onTouchEvent(ev);
                }
                if (mVerticalDrag) {
                    mVerticalDrag = false;
                    return verticalDrag(ev);
                }
            }
        }
        // Set both flags to false in case user lifted finger in the parent view pager
        mHorizontalDrag = false;
        mVerticalDrag = false;

        return false;
    }


    private boolean verticalDrag(MotionEvent ev) {
        final float x = ev.getX();
        final float y = ev.getY();
        ev.setLocation(y, x);
        return super.onTouchEvent(ev);
    }
}

这无法正常工作..即使是android源代码版本也没有..它的故障,仅适用于右/左手势..如果您进行上/下操作,它不会滚动..至少对我来说..
Mohammad Zekrallah


0

这是一个垂直可滚动的ViewPager实现,可与RecyclerView和ListView很好地配合使用。guochong / VerticalViewPager

使用ViewPager.PageTransformer可使ViewPager垂直滚动,并提供View.OnTouchListener来处理滚动冲突。

/**
 * 1.dispatch ACTION_DOWN,ACTION_UP,ACTION_CANCEL to child<br>
 * 2.hack ACTION_MOVE
 *
 * @param v
 * @param e
 * @return
 */
@Override
public boolean onTouch(View v, MotionEvent e) {
    Log.i(TAG, "onTouchEvent " + ", action " + e.getAction() + ", e.rawY " + e.getRawY() + ",lastMotionY " + lastMotionY + ",downY " + downY);
    switch (e.getAction()) {
        case MotionEvent.ACTION_DOWN:
            downY = e.getRawY();
            break;
        case MotionEvent.ACTION_MOVE:

            if (downY == Float.MIN_VALUE && lastMotionY == Float.MIN_VALUE) {
                //not start from MOTION_DOWN, the child dispatch this first motion
                downY = e.getRawY();
                break;
            }

            float diff = e.getRawY() - (lastMotionY == Float.MIN_VALUE ? downY : lastMotionY);
            lastMotionY = e.getRawY();
            diff = diff / 2; //slow down viewpager scroll
            Log.e(TAG, "scrollX " + dummyViewPager.getScrollX() + ",basescrollX " + dummyViewPager.getBaseScrollX());

            if (dummyViewPager.getScrollX() != dummyViewPager.getBaseScrollX()) {
                if (fakeDragVp(v, e, diff)) return true;
            } else {
                if (ViewCompat.canScrollVertically(v, (-diff) > 0 ? 1 : -1)) {
                    Log.e(TAG, "scroll vertically  " + diff + ", move.lastMotionY " + e.getY());
                    break;
                } else {
                    dummyViewPager.beginFakeDrag();
                    fakeDragVp(v, e, diff);
                    adjustDownMotion(v, e);
                    return true;
                }
            }

            break;
        case MotionEvent.ACTION_UP:
        case MotionEvent.ACTION_CANCEL:
            if (dummyViewPager.isFakeDragging()) {
                try {
                    dummyViewPager.endFakeDrag();
                } catch (Exception e1) {
                    Log.e(TAG, "", e1);
                }
            }
            reset();
            break;
    }

    return false;
}

欢迎使用StackOverflow,并感谢您的帮助。您可能想通过添加一些代码来使答案更好。
Elias MP

0

甚至我在交换X和Y来使ViewPager垂直时也遇到了相同的问题。它一点也不平滑。

这是因为它过去仅在滑动角度小于7.125度=拦截时为arctan(1/8)且触摸时小于14度= arctan(1/4)时才有效;与原始ViewPager水平一样,当拦截时滑动角度小于26.565度=反正切(1/2)而触摸时小于45度=反正切(1)时起作用。

这就是为什么我复制Android support-core-ui的代码并将值移到变量中,然后使用反射将其相乘的原因。

请找到的代码和README https://github.com/deepakmishra/verticalviewpager 和VerticalViewPager在https://github.com/deepakmishra/verticalviewpager/blob/master/app/src/main/java/com/viewpager/VerticalViewPager .java


0

更好的方法是将viewpager旋转90度,并使用constraintLayout调整位置。


0

我最终创建了一个新的DirectionalViewPager,它可以垂直或水平滚动,因为我在这里看到的所有解决方案都有缺陷:

  1. 现有的VerticalViewPager实现(由castorflex和LambergaR实现)

    • 它们基于非常老的支持库版本。
  2. 坐标交换的转换技巧

    • 仍然从左/右边缘显示过卷轴。
    • 页面翻转无法正常工作,因为即使交换了坐标,VelocityTracker.computeCurrentVelocity仍会使用X轴计算速度,这可能是因为它在内部使用了忽略坐标交换的本机调用。
  3. 查看旋转

    • 也需要旋转每个子视图的Hack。
    • 如果要读取其他坐标,则必须交换轴。
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.