我有一个VerticalViewPager
,其中每个子片段包含类似
<MyScrollView>
<LinearLayout orientation=vertical>
...
...
</LinearLayout>
</MyScrollView>
当MyScrollView
滚动到底部时,我希望VerticalViewPager
启动并发挥其魔力。同样,如果我将MyScrollView
滚动到顶部。
我试验了一大堆拦截ScrollView
中的触摸事件以某种方式将MotionEvent
发送到VerticalViewPager
而没有任何好运。
这显然不起作用,但为了让谈话继续进行,我目前在MyScrollView
override fun onInterceptTouchEvent(ev: MotionEvent?): Boolean {
return super.onInterceptTouchEvent(ev) && atBottom
}
override fun onScrollChanged(l: Int, t: Int, oldl: Int, oldt: Int) {
atBottom = getChildAt(0).bottom <= (height + scrollY)
super.onScrollChanged(l, t, oldl, oldt)
}
这种行为不稳定,不值得信任,根本不是。非常感谢任何输入!
答案 0 :(得分:0)
这里的解决方案可能非常类似于此: (原始答案是针对webview,但逻辑是相同的)
答案 1 :(得分:0)
我认为让ViewPager启动时让ScrollView指示的想法非常好,它已经使用requestDisallowInterceptTouchEvent
来阻止ViewPager拦截滚动。您需要的是使用相同的方法允许在您指示的情况下截取,即ScrollView到达顶部或底部时。
因此,如果ScrollView处理了ACTION_MOVE
触摸事件,但得到的滚动偏移没有改变,我们可以假设我们已经滚过顶部或底部(现在已经过度滚动)。可能有更好的方法来检测过度滚动,因此请以此为出发点进行实验:
//MyScrollView.java
@Override
public boolean onTouchEvent(MotionEvent ev) {
boolean handled = super.onTouchEvent(ev);
if (handled && ev.getActionMasked() == MotionEvent.ACTION_MOVE) {
int y = getScrollY();
boolean moved = y != prevY;
prevY = y;
// This is the important part to allow the parent to intercept
if (!moved) {
ViewParent parent = getParent();
if (parent != null) {
parent.requestDisallowInterceptTouchEvent(false);
}
}
// Also important to re
return moved;
}
return handled;
}
编辑 - 我快速玩了一下,认为这很好用
public class MyScrollView extends ScrollView {
private boolean clampedY;
public MyScrollView(Context context) {
super(context);
}
public MyScrollView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public MyScrollView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
@Override
public boolean onTouchEvent(MotionEvent ev) {
boolean handled = super.onTouchEvent(ev);
if (handled) {
ViewParent parent = getParent();
switch (ev.getActionMasked()) {
case MotionEvent.ACTION_MOVE:
if (clampedY && parent != null) {
parent.requestDisallowInterceptTouchEvent(false);
}
break;
case MotionEvent.ACTION_DOWN:
clampedY = false;
if (parent != null) {
parent.requestDisallowInterceptTouchEvent(true);
}
break;
}
}
return handled;
}
@Override
protected void onOverScrolled(int scrollX, int scrollY, boolean clampedX, boolean clampedY) {
super.onOverScrolled(scrollX, scrollY, clampedX, clampedY);
this.clampedY = clampedY;
}
}
编辑2 - 如果有任何滚动,这将保留触摸的所有权,因此切换页面需要单独触摸
public class MyScrollView extends ScrollView {
private boolean scrolled;
public MyScrollView(Context context) {
super(context);
}
public MyScrollView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public MyScrollView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
@Override
public boolean onTouchEvent(MotionEvent ev) {
boolean handled = super.onTouchEvent(ev);
if (handled) {
ViewParent parent = getParent();
switch (ev.getActionMasked()) {
case MotionEvent.ACTION_MOVE:
if (!scrolled && parent != null) {
parent.requestDisallowInterceptTouchEvent(false);
}
break;
case MotionEvent.ACTION_DOWN:
scrolled = false;
if (parent != null) {
parent.requestDisallowInterceptTouchEvent(true);
}
break;
}
}
return handled;
}
@Override
protected void onScrollChanged(int l, int t, int oldl, int oldt) {
super.onScrollChanged(l, t, oldl, oldt);
if (t != oldt) {
scrolled = true;
}
}
}