有没有办法制作不水平滚动但垂直滚动的
ViewPager
? #1 楼
您可以使用ViewPager.PageTransformer给出垂直ViewPager
的错觉。要实现垂直滚动而不是水平拖动的滚动,您必须覆盖ViewPager
的默认触摸事件,并在处理它们之前交换MotionEvent
的坐标,例如:/**
* 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));
}
}
当然,您可以根据自己的喜好调整这些设置。
最终看起来像这样:
评论
@Der Golem如何使用布局?
– bShah
14年6月16日在9:17
确切的问题是什么?顺便说一句,我没有发布答案,只是添加了引用的图像。
–Phantômaxx
14年6月16日在9:21
在这个示例中,@ Brett我想在左右滑动时执行一些操作。怎么做
–螃蟹
15年11月18日在7:06
@Brett可以正常工作,过渡正在垂直进行。但是问题是我必须向右/向左滑动以进行过渡,并且在向上/向下滑动时不会发生过渡。
– Karan Khurana
16年2月12日在13:15
@Brett我正在使用您的解决方案。但现在我在ororid馅饼设备中遇到了刷卡问题。是否有人面临相同的问题?
–吉桑
19年1月3日在10:38
#2 楼
Vertical ViewPager这里的其他答案似乎都与它们有关。甚至推荐的开源项目也没有将最近的请求请求与错误修复合并。然后我从Google找到一个
VerticalViewPager
,他们使用了一些DeskClock应用程序。我相信使用Google的实现比这里提供的其他答案要多得多。 (Google的版本与当前投票最多的答案相似,但更彻底。)完整示例
该示例与我的基本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>
<?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
我只将
VerticalViewPager
换成了ViewPager
。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;
}
}
}
完成
您应该能够运行该应用程序并在动画中查看结果上面。
另请参见
基本ViewPager示例
带有FragmentPagerAdapter的ViewPager
评论
代码可以正常工作,只需要1个小帮助即可。在当前代码中,我们需要从下往上滑动才能获取下一页,但是我希望即使是很小的滑动也可以得到下一页。
– AMIT
19年3月26日在9:21
@AMIT是否找到了解决方案?有同样的问题
– Yupi
12月14日下午16:04
#3 楼
我有一个适用于我的解决方案,分两个步骤进行。onInstantiateItem()
的PagerAdapter
,创建视图并将其旋转-90:view.setRotation(-90f)
如果使用
FragmentPagerAdapter
,则:objFragment.getView().setRotation(-90)
将
ViewPager
视图旋转90度:objViewPager.setRotation(90)
至少对于我的需求来说,它就像是一种魅力。
评论
此解决方案有效,但是您仍然必须水平滑动,而viewPager现在垂直滚动
–leochab
2014年1月9日在12:48
@库莱我不知道该怎么办,根据我的理解,您可以解释一下吗,因为我们有公共对象InstantiateItem(ViewGroup container,int position),在这里我们需要做container.setRotation(-90f);
– varun
2014年1月29日在12:03
这样做就像一种魅力! Althoug视图被切掉了顶部和底部,我不知道为什么:-/
– NivaldoBondança
14年4月28日在16:55
它适用于正方形图像而不适用于矩形图像。旋转矩形时尺寸会出错。
–库莱
2014年5月9日下午5:02
我不确定谁赞成这个答案。这不是VerticalViewPager,这是旋转90度的ViewPager,手势和过渡恰好相反。而且根本不是自然的
– droidev
19年7月12日在3:19
#4 楼
对于正在努力使垂直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
17-10-16在2:17
从教程开始-vogella.com/tutorials/AndroidCustomViews/article.html
–潜水员
17-10-16在7:03
如何在视图中实现上述“水平和垂直”视图寻呼机类?代码段有助于
–user1810931
17-10-16在13:33
ViewPager已经在查看,我不明白您的要求。
–潜水员
17-10-16在14:33
我正在使用一个名为“材料日历视图”的库(github.com/prolificinteractive/material-calendarview),它已经具有水平viewpager,我想在其中添加垂直viewpager。
–user1810931
17-10-16在14:47
#5 楼
稍微扩展一下此答案即可帮助我达到要求(“垂直视图传呼机”以类似“短裤”的动画-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));
}
}
我希望这可能对您有所帮助给别人。
评论
MIN_SCALE的理想值?
–divyenduz
2015年12月2日于10:52
您是否发现快速滑动过渡不顺利的问题
–万能
16-2-26在10:31
到底为什么有人会快速刷卡?
– Amrut Bidri
16年2月28日在9:16
只是需要澄清的一句话:此解决方案更改动画的方式是,新页面不是从下面而是在旧页面后面。因此,基本上,您没有将页面并排放置,而是将一叠页面并排放置。因此,此解决方案可能不是原始问题要解决的问题。
–本杰明·巴斯马奇(Benjamin Basmaci)
19年5月13日在15:19
#6 楼
有一些开源项目声称可以做到这一点。它们是:kaelaela / VerticalViewPager,最新提交于2015年10月,一位贡献者
castorflex / VerticalViewPager,最新提交于2014年2月,以及三位贡献者
LambergaR / VerticalViewPager /,2013年8月的最新提交,一位贡献者
这些作者被标记为已弃用:
不推荐使用:JakeWharton的Android Directional-ViewPager https://github.com/JakeWharton/Android-DirectionalViewPager
还有另外一件事:
deskclock
应用程序的Android源代码中也有一个文件名为VerticalViewPager.java的文件,但由于我找不到有关它的文档,因此似乎未得到官方支持。#7 楼
检查一下:https://github.com/JakeWharton/Android-DirectionalViewPager或者以下问题可能对您有所帮助:垂直“带有页面的Gridview”或“ Viewpager”
评论
需要记住的一点是DirectionalViewPager已有相当一段时间没有更新,因此缺少支持库中ViewPager的一些较新功能。即setPageMargin(int)。通常,它应该可以完成这项工作。如果不是这样,获取ViewPager的源代码并换出所有x / y和width / height逻辑也不太麻烦。
– MH。
2012年11月20日在18:29
我已经考虑过DirectionalViewPager,但是,正如MH所说,它没有更新(开发人员认为它已弃用)!令人难以置信的是,Android开发人员没有向社区提供垂直的ViewPager,而只是水平的。我是Android的新手,开发垂直ViewPager换出x / y对我来说并不容易。.我更喜欢已经构建的解决方案..无论如何,谢谢
–user1709805
2012年11月21日在8:13
嗨,您是否成功进行了垂直viewpager?坦斯克
– Paul
13年2月14日在18:14
#8 楼
由于设备显示为矩形,因此对@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的答案发表了评论。
评论
我总是通过在onInterceptTouchEvent中返回true进行了一些改进,并且还修改了Key绑定,因此使用DPAD可以触发UP / DOWN滚动,而不是向左/向右滚动:gist.github.com/zevektor/fbacf4f4f6c39fd6e409
–Vektor88
15年7月8日在8:03
@ Vektor88始终返回true将阻止内部视图接收触摸事件..最佳解决方案如brett回答..
–穆罕默德·泽克拉拉
2015年12月8日在10:04
#9 楼
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);
}
}
评论
这工作得很好,但是我失去了元素上的touch Event或left / swipe事件...
– matias fha
2014年8月31日在19:20
#10 楼
我最终创建了一个新的DirectionalViewPager,它可以垂直或水平滚动,因为我在这里看到的所有解决方案都有缺陷:现有的VerticalViewPager实现(由castorflex和LambergaR)
它们基于非常老的支持库版本。
带有坐标交换的转换技巧
仍然从左/右边缘显示过卷轴。
页面翻转无法正常工作,因为即使交换了坐标,
VelocityTracker.computeCurrentVelocity
仍会计算X轴的速度,可能是因为这在内部使用忽略坐标交换的本机调用。视图旋转
需要每个子视图为也要旋转。
如果要读取其他坐标,则必须交换轴。
评论
但我认为它不支持PageTransformer,因为DirectionalViwePager没有覆盖viewpager
–薛庆
9月9日下午6:19
#11 楼
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源代码版本也没有..它的故障,仅适用于左右手势..如果向上/向下,它至少不会滚动..
–穆罕默德·泽克拉拉
16年2月7日在8:26
#12 楼
这是一个垂直可滚动的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
17年9月5日在11:45
#13 楼
甚至我在通过交换X和Y来使ViewPager垂直时也遇到了同样的问题。它根本不平滑。那是因为它过去仅在滑动角度小于7.125度=时才起作用。截距时为arctan(1/8),触摸时为14度= arctan(1/4);作为原始ViewPager水平的一种作品,当滑动角度小于26.565度=截距时为arctan(1/2)且触摸时小于45度= arctan(1)时。
这就是为什么我复制代码的原因Android support-core-ui并将其值移动到变量,我使用反射将其相乘。
请在https://github.com/deepakmishra/verticalviewpager
找到代码和自述文件
和VerticalViewPager,位于https://github.com/deepakmishra/verticalviewpager/blob/master/app/src/main/java/com/viewpager/VerticalViewPager.java
评论
垂直ViewPager有一个新的非官方开源实现:公告:plus.google.com/107777704046743444096/posts/1FTJfrvnY8w代码:github.com/LambergaR/VerticalViewPagerAntoine Merle的垂直视图传呼机实现:github.com/castorflex/VerticalViewPager
有一个基于19支持库的新实现:github.com/castorflex/VerticalViewPager
尽管名称相似,但这与github.com/castorflex/VerticalViewPager不同。
有一个名为ViewPager2的控件,请在此处检查以了解演示stackoverflow.com/a/54643817/7666442