转
google官方是不提倡在UI中嵌套可滚动控件,如ScrollView,ViewPager等,但有时候为了实现一定的效果也不得不用,其实很多知名App都是这样弄的。下面是我总结的两种嵌套情形。
一.当ScrollView中嵌套ViewPager的情形
这种比较常见,一般是在界面的最顶部放置一个ViewPager,用来展示图片还有一些文字说明,下面则是List,像之前版本的网易新闻客户端就是这样的效果。List滚动的同时ViewPager也会跟着滚动,这时候就要用到ScrollView中嵌套ViewPager。
由于ScrollView是垂直滚动的,ViewPager是水平滑动的。当在ViewPager上滑动的时候,如果在水平方向上的偏移量较垂直方向上的偏移量不是太大的时候,会有明显的ScrollView滚动问题,很影响用户体验。解决的方法我总结了两种:
1.用自定义ScrollView,通过覆写dispatchTouchEvent,onInterceptTouchEvent,onTouchEvent等方法,来人为的控制TouchEvent。于是在网上搜了下,从点击打开链接找到了一个方法。覆写ScrollView的onInterceptTouchEvent方法,通过对水平和垂直方向上的偏移量进行计算,让ScrollView决定是拦截TouchEvent还是传递给子View。试了下,效果挺好的,代码如下:
- @Override
- public boolean onInterceptTouchEvent(MotionEvent ev) {
- switch (ev.getAction()) {
- case MotionEvent.ACTION_DOWN:
- xDistance = yDistance = 0f;
- xLast = ev.getX();
- yLast = ev.getY();
- break;
- case MotionEvent.ACTION_MOVE:
- final float curX = ev.getX();
- final float curY = ev.getY();
- xDistance += Math.abs(curX - xLast);
- yDistance += Math.abs(curY - yLast);
- xLast = curX;
- yLast = curY;
- if(xDistance > yDistance){
- return false;
- }
- }
- return super.onInterceptTouchEvent(ev);
- }
- boolean ret = super.dispatchTouchEvent(ev);
- if(ret)
- {
- requestDisallowInterceptTouchEvent(true);
- }
- return ret;
二.ViewPager中嵌套ScrollView,ScrollView中嵌套ViewPager
这种情况下,在ScrollView中嵌套的子ViewPager上滑动的时候该ViewPager并不会切换,而是切换父ViewPager。这时候,只能自定义ViewPager了,方法跟情形一中的第二种方法是一样的,效果也挺好的。使该子ViewPager获得TouchEvent而不传递给父及祖先控件。