ViewPager 内的 ScrollView:滑动不工作
ScrollView inside ViewPager: swipe not working
我有包含三个片段的 ViewPager,其中之一是带有 ScrollView 的 FrameLayout:
<FrameLayout 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">
<ScrollView
android:layout_width="match_parent"
android:layout_height="wrap_content">
<LinearLayout
android:id="@+id/table"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"/>
</ScrollView>
<Button
android:id="@+id/buttonRemove"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/bg_button_red"
android:layout_gravity="bottom"
android:layout_margin="4dp"
android:text="@string/button_remove_last_round"
android:textColor="#ffffff"
android:textSize="24sp"/>
</FrameLayout>
如果我在按钮上滑动,它就会起作用。但是如果我在 ScrollView 上滑动,它不起作用,只有滚动 up/down 有效
编辑:我试图覆盖 Scrollview 的 OnTouchEvent:
@Override
public boolean onTouchEvent(MotionEvent ev) {
switch (ev.getAction()){
case MotionEvent.ACTION_DOWN:
touchX = ev.getX();
touchY = ev.getY();
return super.onTouchEvent(ev);//if I change it to 'break', then only swipe works, but no scroll
case MotionEvent.ACTION_MOVE:
if(Math.abs(touchX-ev.getX())<40){
return super.onTouchEvent(ev);//Scroll works perfectly
}else{
return false;//Scroll disabled, but swipe still not working
}
case MotionEvent.ACTION_CANCEL:
case MotionEvent.ACTION_UP:
touchX=0;
touchY=0;
break;
}
return false;
}
现在我可以关闭scroll了,但是swipe还是不行,如果X点之间的差超过40,我把事件传给viewpager,但是viewpager的onTouchListener没有得到这个事件;
问题是不清楚你想要发生什么滚动,是 ViewPager 的滚动还是滚动视图的滚动。如果你真的需要滚动内部滚动,那么你需要覆盖内部滚动视图的 OnTouchListener 并添加决定何时捕获和使用触摸以及何时将其传递回父视图的代码。
在这种情况下,您可以做一些事情来测试滑动是否 up/down,然后保持触摸,否则如果滑动是横向的,则将其传回。
好的,我在@yedidyak 的帮助下找到了解决方案。我写了我的自定义 ScrollView:
public class CustomScrollView extends ScrollView {
float touchX = 0;
float touchY = 0;
ViewPager parentPager;
public void setParentPager(ViewPager parentPager) {
this.parentPager = parentPager;
}
public CustomScrollView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public CustomScrollView(Context context) {
super(context);
}
@Override
public boolean onTouchEvent(MotionEvent ev) {
switch (ev.getActionMasked()){
case MotionEvent.ACTION_DOWN:
touchX = ev.getX();
touchY = ev.getY();
return super.onTouchEvent(ev);
case MotionEvent.ACTION_MOVE:
if(Math.abs(touchX-ev.getX())<40){
return super.onTouchEvent(ev);
}else{
if (parentPager==null) {
return false;
} else {
return parentPager.onTouchEvent(ev);
}
}
case MotionEvent.ACTION_CANCEL:
case MotionEvent.ACTION_UP:
touchX=0;
touchY=0;
break;
}
return super.onTouchEvent(ev);
}
}
然后在片段中,我将 viewpager 放到这个视图中,它工作得很好
For Future Readers living in +2019
使用ViewPager2 来避免这个问题。
您可以在此 .
找到 ViewPager2 实现的良好示例
我有包含三个片段的 ViewPager,其中之一是带有 ScrollView 的 FrameLayout:
<FrameLayout 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">
<ScrollView
android:layout_width="match_parent"
android:layout_height="wrap_content">
<LinearLayout
android:id="@+id/table"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"/>
</ScrollView>
<Button
android:id="@+id/buttonRemove"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/bg_button_red"
android:layout_gravity="bottom"
android:layout_margin="4dp"
android:text="@string/button_remove_last_round"
android:textColor="#ffffff"
android:textSize="24sp"/>
</FrameLayout>
如果我在按钮上滑动,它就会起作用。但是如果我在 ScrollView 上滑动,它不起作用,只有滚动 up/down 有效
编辑:我试图覆盖 Scrollview 的 OnTouchEvent:
@Override
public boolean onTouchEvent(MotionEvent ev) {
switch (ev.getAction()){
case MotionEvent.ACTION_DOWN:
touchX = ev.getX();
touchY = ev.getY();
return super.onTouchEvent(ev);//if I change it to 'break', then only swipe works, but no scroll
case MotionEvent.ACTION_MOVE:
if(Math.abs(touchX-ev.getX())<40){
return super.onTouchEvent(ev);//Scroll works perfectly
}else{
return false;//Scroll disabled, but swipe still not working
}
case MotionEvent.ACTION_CANCEL:
case MotionEvent.ACTION_UP:
touchX=0;
touchY=0;
break;
}
return false;
}
现在我可以关闭scroll了,但是swipe还是不行,如果X点之间的差超过40,我把事件传给viewpager,但是viewpager的onTouchListener没有得到这个事件;
问题是不清楚你想要发生什么滚动,是 ViewPager 的滚动还是滚动视图的滚动。如果你真的需要滚动内部滚动,那么你需要覆盖内部滚动视图的 OnTouchListener 并添加决定何时捕获和使用触摸以及何时将其传递回父视图的代码。
在这种情况下,您可以做一些事情来测试滑动是否 up/down,然后保持触摸,否则如果滑动是横向的,则将其传回。
好的,我在@yedidyak 的帮助下找到了解决方案。我写了我的自定义 ScrollView:
public class CustomScrollView extends ScrollView {
float touchX = 0;
float touchY = 0;
ViewPager parentPager;
public void setParentPager(ViewPager parentPager) {
this.parentPager = parentPager;
}
public CustomScrollView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public CustomScrollView(Context context) {
super(context);
}
@Override
public boolean onTouchEvent(MotionEvent ev) {
switch (ev.getActionMasked()){
case MotionEvent.ACTION_DOWN:
touchX = ev.getX();
touchY = ev.getY();
return super.onTouchEvent(ev);
case MotionEvent.ACTION_MOVE:
if(Math.abs(touchX-ev.getX())<40){
return super.onTouchEvent(ev);
}else{
if (parentPager==null) {
return false;
} else {
return parentPager.onTouchEvent(ev);
}
}
case MotionEvent.ACTION_CANCEL:
case MotionEvent.ACTION_UP:
touchX=0;
touchY=0;
break;
}
return super.onTouchEvent(ev);
}
}
然后在片段中,我将 viewpager 放到这个视图中,它工作得很好
For Future Readers living in +2019
使用ViewPager2 来避免这个问题。
您可以在此