垂直viewpager 嵌套ScrollView的解决办法
来源:互联网 发布:电影 《人工智能》 编辑:程序博客网 时间:2024/05/22 03:27
最近要做一个这种实现,在网上搜了一圈,据说已解决的办法几乎全试过了,结果就没一个可以的,没办法,只能自己写了,目前我的实现只包含两页fragment,更多页数可以类推。
首先实现思想是,外部拦截,即在垂直viewpager的onInterceptTouchEvent事件中对当前页面内scrollview的滑动状态进行判定(false表示触摸事件传递到子view,true表示viewpager自行处理),并确定返回值。
1、页面处于第一页,scrollview滑动到底部并且触摸事件为向上滑动时 onInterceptTouchEvent 返回true,其他情况返回false
2、页面出鱼第二页,scrollview滑动到顶部并且触摸事件为向下滑动时 onInterceptTouchEvent 返回true,其他情况返回false
基于这种思想的实现在实测时,发现viewpager经常会有另一页的小部分显示出来,viewpager加上滑动监听后发现,例如在第一页滑动时,viewpager确实向上滑动了,但是onInterceptTouchEvent 没有返回过true值。具体导致该问题的原因目前还不清楚。为了解决这个问题,我重写了viewpager的scrollTo方法,设置成只有在我设置的viewpager滑动标志位为true时viewpager才调用scrollTo方法,其实就是判断并禁止viewpager滑动。 以下是viewpager和scrollview的代码。
垂直viewpager的代码:
/** * Created by YU_ZERO on 15/12/28. */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; } //我的代码 //scrollview距离底部的距离 private int diffTop = 100; //scrollview滑动的距离 private int scrollYBottom = -100; //是否在向上滑动 private boolean isSlip2Up = true; //第一页scrollview public VerticalScrollView topScrollView; //第二页scrollview public VerticalScrollView bottomScrollView; private int mLastX; private int mLastY; //滑动至第二页时,第一页子View长度是否变化,如果子页中view长度不会发生变化,可去掉该标志位 private boolean isTopLenChanged = false; //是否拦截触摸事件 private boolean intercept = false; @Override public boolean onInterceptTouchEvent(MotionEvent ev){ super.onInterceptTouchEvent(swapXY(ev)); swapXY(ev); int x = (int) ev.getX(); int y = (int) ev.getY(); Activity activity = (Activity) getContext(); if(topScrollView==null || bottomScrollView==null){ topScrollView = (VerticalScrollView) activity.findViewById(R.id.top_scrollview); bottomScrollView = (VerticalScrollView) activity.findViewById(R.id.bottom_scrollview); } diffTop = topScrollView.diff; scrollYBottom = bottomScrollView.scrollY; boolean tis2Bottom = diffTop==0? true: false; boolean bis2Top = scrollYBottom==0? true: false; intercept = false; switch (ev.getAction()){ case MotionEvent.ACTION_DOWN: mLastX = x; mLastY = y; isSlip2Up = false; intercept = false; break; case MotionEvent.ACTION_UP: intercept = false; isSlip2Up = false; mLastX = mLastY = 0; break; case MotionEvent.ACTION_MOVE: int deltaX = x - mLastX; int deltaY = y - mLastY; if(Math.abs(deltaY)>Math.abs(deltaX)){ isSlip2Up = deltaY<0? true: false; } if(getCurrentItem()==0){ if(!tis2Bottom){ isSlip2Up = true; } if(!isSlip2Up){ tis2Bottom = false; } //第一页,当scrollview滑动至底部,手势向上滑动,且该页子view长度没有变化时拦截事件 intercept = tis2Bottom && isSlip2Up && !isTopLenChanged; } else if(getCurrentItem()==1){ //第二页,当scrollview滑动至顶部且手势向下滑动时拦截事件 intercept = bis2Top && !isSlip2Up; } break; case MotionEvent.ACTION_CANCEL: intercept = false; isSlip2Up = false; mLastX = mLastY = 0; break; } return intercept; } public void setIsTopLenChanged(boolean isTopLenChanged) { this.isTopLenChanged = isTopLenChanged; } @Override public void scrollTo(int x, int y) { //仅当viewpager滑动标志位为true时,才允许viewpager滑动 if (intercept){ super.scrollTo(x, y); } } @Override public boolean onTouchEvent(MotionEvent ev) { return super.onTouchEvent(swapXY(ev)); }}
垂直scrollview:
/** * Created by YU_ZERO on 15/12/28. */public class VerticalScrollView extends ScrollView { public int diff = 100; public int scrollY = 0; public VerticalScrollView(Context context, AttributeSet attrs) { super(context, attrs); setFadingEdgeLength(0); } @Override protected void onScrollChanged(int l, int t, int oldl, int oldt) { diff = getScrollY() + getHeight() - computeVerticalScrollRange(); scrollY = getScrollY(); //以下为当scrollview内子控件高度发生变化时,设置的值,高度如果没有变化,可去掉以下代码 if(getTag()!=null){ if(getTag() instanceof FragmentGoodsDetailsVerticalTop){ ((GoodsDetailsVertical)((FragmentGoodsDetailsVerticalTop) getTag()).getActivity()).getPager().setIsTopLenChanged(false); } else if(getTag() instanceof FragmentGoodsDetailsVerticalBottom){ } } super.onScrollChanged(l, t, oldl, oldt); } @Override public boolean onInterceptTouchEvent(MotionEvent ev) { return super.onInterceptTouchEvent(ev); }}
0 0
- 垂直viewpager 嵌套ScrollView的解决办法
- ScrollView嵌套ViewPager冲突的解决办法
- scrollview 嵌套 viewpager 滑动冲突的解决办法
- 在ScrollView中嵌套ViewPager,ViewPager不能显示的解决办法
- 【事件冲突】ScrollView嵌套ViewPager冲突的解决办法
- ScrollView嵌套GridView的解决办法
- ScrollView嵌套GridView的解决办法
- ScrollView嵌套GridView的解决办法
- ScrollView嵌套GridView的解决办法
- ScrollView嵌套GridView的解决办法
- ScrollView嵌套GridView的解决办法
- ScrollView嵌套GridView的解决办法
- ScrollView嵌套ListView的解决办法
- ScrollView嵌套GridView的解决办法
- ScrollView嵌套GridView的解决办法
- ScrollView嵌套ViewPager,导致滑动不畅,以及不显示的解决办法
- android中viewpager,scrollview的嵌套问题
- android中viewpager,scrollview的嵌套问题
- java使用oracle的存储过程和函数区别
- 安卓代码规范
- /jsp/wlxy/xxzx_zsJ.jsp(9,3) invalid directive
- Android驱动调试步骤(新出厂的第一版硬件必须遵守)
- 沈向洋谈做研究的那些事儿
- 垂直viewpager 嵌套ScrollView的解决办法
- 调整UIButton上图片的位置和大小
- Linux本地套接字
- android解决使用CountDownTimer出现的时间不稳定问题(执行多次变化加快)
- Android系统启动过程
- 在Windows操作系统中,如何终止占有的8080端口的tomcat进程
- JSP Tomcat8.0运行连接池时发生异常【AbstractMethodError oracle.jdbc.driver.T4CConnection.isValid(I)Z】
- 【学习笔记javascript设计模式与开发实践(发布--订阅模式)----8】
- launchMode带来的onActivityResult失效问题