我有一个包含水平滚动视图 (HSV) 的视图寻呼机 (VP)。如果 HSV 到达它的一个边缘或根本无法滚动,则在阻止方向上的新滑动时,VP 应接管滚动到下一页。我犹豫着问这个问题,因为我发现了类似的问题:
我可以在 Android 的 Viewpager 中使用 Horizontal Scrollview 吗?
或者
但该解决方案对我不起作用。'v instanceof HorizontalScrollView' 为真,但 viewPager 不滚动
任何其他想法如何实现所需的行为?
public class MyViewPager extends ViewPager {
public MyViewPager(Context context, AttributeSet attrs) {
super(context, attrs);
}
// Update 1
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
return true;
//return super.onInterceptTouchEvent(ev);
}
/**
* https://stackoverflow.com/questions/22781496/can-i-use-horizontal-scrollview-inside-a-viewpager-in-android
*/
@Override
protected boolean canScroll(View v, boolean checkV, int dx, int x, int y) {
if (v instanceof HorizontalScrollView) {
return true;
}
return super.canScroll(v, checkV, dx, x, y);
}
}
子视图:view_pager_page.xml:
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
>
<FrameLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center">
<HorizontalScrollView
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center">
<include layout="@layout/" />
</LinearLayout>
</HorizontalScrollView>
</LinearLayout>
</FrameLayout>
</RelativeLayout>
父视图:view_pager.xml
<android.support.design.widget.CoordinatorLayout>
...
<LinearLayout>
<packagepath.MyViewPager
android:layout_width="match_parent"
android:layout_height="wrap_content">
</packagepath.MyViewPager>
</LinearLayout>
...
<android.support.design.widget.CoordinatorLayout>
更新 1:当覆盖 'onInterceptTouchEvent' 并让它始终返回真正的 VP 滚动时,但 HSV 不会。我认为只有当 HSV 到达边缘时才必须返回 true 吗?如果是这种情况,我如何在这种方法中弄清楚?
更新2:我重构了android的触摸事件机制,希望能对如何拦截运动事件流有所了解。例如,在 HSV 中,我可以简单地返回 false 以让 VP 使用此事件和所有后续运动事件。不幸的是,我需要两个 MotionEvent.MOVE 类型的运动事件来决定当到达边缘时 HSV 还是 VP 应该滚动(如果 HSV 已经到达右边缘,向右滑动将 HSV 向后滚动,向左滑动滚动到 VP 的下一页)。但是,如果我跳过 MotionEvent.DOWN 操作,HSV 或 VP 都不会开始滚动……太难解决了。有任何想法吗?
(警告:图不完整,会有错误,请大家指正:-))
更新 3:最后我让它工作了。理解Touchevent机制帮助很大,也是ZeroOne的第一条评论。当我有时间时,我会发布我的解决方案。
1.扩展ViewPager类:
public class ViewPagerContainingHorizontalScrollView extends ViewPager {
private Float x_old;
private boolean bDoIntercept = false;
private boolean bHsvRightEdge = false;
private boolean bHsvLeftEdge = true;
public ViewPagerContainingHorizontalScrollView(Context context, AttributeSet attrs) {
super(context, attrs);
}
private float calculateDistanceSwipe(MotionEvent ev){
float distance = 0;
if (x_old == null) {
x_old = ev.getX();
} else {
distance = ev.getX() - x_old;
x_old = null;
}
return distance;
}
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
mDoIntercept = false;
if(ev.getAction() == MotionEvent.ACTION_MOVE) {
float distance = calculateDistanceSwipe(ev);
if (distance < 0) {//scrolling left direction
if (bHsvRightEdge) { //HSV right edge
bDoIntercept = true;
//When scrolling slow VP may not switch page.
//Then HSV snaps back into old position.
//To allow HSV to scroll into non blocked direction set following to false.
bHsvRightEdge = false;
}
bHsvLeftEdge = false;//scrolling left means left edge not reached
} else if (distance > 0) {//scrolling right direction
if (bHsvLeftEdge) { //HSV left edge
bDoIntercept = true;
//When scrolling slow VP may not switch page.
//Then HSV snaps back into old position.
//To allow HSV to scroll into non blocked direction set following to false.
bHsvLeftEdge = false;
}
bHsvRightEdge = false;//scrolling right means right edge not reached
}
}
return super.dispatchTouchEvent(ev);
}
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
if(bDoIntercept){
return true;
}else{
return super.onInterceptTouchEvent(ev);
}
}
@Override
protected boolean canScroll(View v, boolean checkV, int dx, int x, int y) {
if (v instanceof HorizontalScrollView) {
HorizontalScrollView hsv = (HorizontalScrollView) v;
int max_scrollX = hsv.getChildAt(0).getWidth() - hsv.getWidth();
int min_scrollX = 0;
int current_scroll_x = hsv.getScrollX();
if (current_scroll_x == max_scrollX) { //HSV right edge
bHsvRightEdge = true;
}
if (current_scroll_x == min_scrollX) { //HSV left edge
bHsvLeftEdge = true;
}
return true;
}
return super.canScroll(v, checkV, dx, x, y);
}
}
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句