android向上拖动查看图文详情控件

摘自:http://blog.csdn.net/qifengdeqingchen/article/details/51659735

 

一、淘宝商品详情页效果

先看一下淘宝详情页的效果




我们的效果



二、实现思路


     使用两个scrollView,两个scrollView 竖直排列,通过自定义viewGroup来控制两个scrollView的竖直排列,以及滑动事件的处理。如下图




三、具体实现


1、继承viewGroup自定义布局View 重写onMeasure()和onLayout方法,在onLayout方法中完成对两个子ScrollView的竖直排列布局,代码如下:
布局文件:

  1. <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  2.     xmlns:tools="http://schemas.android.com/tools"  
  3.     android:layout_width="match_parent"  
  4.     android:layout_height="match_parent"  
  5.     tools:context="com.baoyunlong.view.pulluptoloadmore.MainActivity">  
  6.   
  7.     <com.baoyunlong.view.pulluptoloadmore.PullUpToLoadMore  
  8.         android:layout_width="match_parent"  
  9.         android:layout_height="match_parent"  
  10.         android:orientation="vertical">  
  11.   
  12.         <com.baoyunlong.view.pulluptoloadmore.MyScrollView  
  13.             android:layout_width="match_parent"  
  14.             android:layout_height="match_parent"  
  15.             android:fillViewport="true">  
  16.   
  17.             <LinearLayout  
  18.                 android:layout_width="match_parent"  
  19.                 android:layout_height="match_parent"  
  20.                 android:orientation="vertical">  
  21.   
  22.                 <ImageView  
  23.                     android:scaleType="fitXY"  
  24.                     android:src="@drawable/a1"  
  25.                     android:layout_width="match_parent"  
  26.                     android:layout_height="180dp" />  
  27.   
  28.                 <TextView  
  29.                     android:text="这里是标题"  
  30.                     android:textSize="18dp"  
  31.                     android:layout_marginRight="10dp"  
  32.                     android:layout_marginLeft="10dp"  
  33.                     android:layout_marginTop="10dp"  
  34.                     android:layout_width="match_parent"  
  35.                     android:layout_height="wrap_content" />  
  36.   
  37.                 <TextView  
  38.                     android:layout_marginTop="10dp"  
  39.                     android:text="子标题"  
  40.                     android:layout_marginLeft="10dp"  
  41.                     android:layout_marginRight="10dp"  
  42.                     android:textSize="18dp"  
  43.                     android:layout_width="match_parent"  
  44.                     android:layout_height="wrap_content" />  
  45.   
  46.                ..............  
  47.   
  48.                 <LinearLayout  
  49.                     android:layout_height="0dp"  
  50.                     android:layout_weight="1"  
  51.                     android:gravity="bottom"  
  52.                     android:layout_width="match_parent">  
  53.   
  54.                     <TextView  
  55.                         android:layout_width="match_parent"  
  56.                         android:layout_height="wrap_content"  
  57.                         android:height="50dp"  
  58.                         android:background="#b11"  
  59.                         android:gravity="center"  
  60.                         android:text="继续拖动查看图文详情"  
  61.                         android:textColor="#000" />  
  62.   
  63.                 </LinearLayout>  
  64.             </LinearLayout>  
  65.   
  66.         </com.baoyunlong.view.pulluptoloadmore.MyScrollView>  
  67.   
  68.         <com.baoyunlong.view.pulluptoloadmore.MyScrollView  
  69.             android:layout_width="match_parent"  
  70.             android:layout_height="match_parent"  
  71.             android:fillViewport="true">  
  72.   
  73.             <LinearLayout  
  74.                 android:layout_width="match_parent"  
  75.                 android:layout_height="match_parent"  
  76.                 android:gravity="center"  
  77.                 android:orientation="vertical">  
  78.   
  79.   
  80.                 <ImageView  
  81.                     android:layout_width="wrap_content"  
  82.                     android:layout_height="wrap_content"  
  83.                     android:src="@drawable/a1" />  
  84.   
  85.                 <ImageView  
  86.                     android:layout_width="wrap_content"  
  87.                     android:layout_height="wrap_content"  
  88.                     android:src="@drawable/a3" />  
  89.   
  90.                 .........  
  91.   
  92.   
  93.             </LinearLayout>  
  94.   
  95.         </com.baoyunlong.view.pulluptoloadmore.MyScrollView>  
  96.   
  97.     </com.baoyunlong.view.pulluptoloadmore.PullUpToLoadMore>  
  98.   
  99. </RelativeLayout>  
<RelativeLayout 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"
    tools:context="com.baoyunlong.view.pulluptoloadmore.MainActivity">

    <com.baoyunlong.view.pulluptoloadmore.PullUpToLoadMore
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">

        <com.baoyunlong.view.pulluptoloadmore.MyScrollView
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:fillViewport="true">

            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:orientation="vertical">

                <ImageView
                    android:scaleType="fitXY"
                    android:src="@drawable/a1"
                    android:layout_width="match_parent"
                    android:layout_height="180dp" />

                <TextView
                    android:text="这里是标题"
                    android:textSize="18dp"
                    android:layout_marginRight="10dp"
                    android:layout_marginLeft="10dp"
                    android:layout_marginTop="10dp"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content" />

                <TextView
                    android:layout_marginTop="10dp"
                    android:text="子标题"
                    android:layout_marginLeft="10dp"
                    android:layout_marginRight="10dp"
                    android:textSize="18dp"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content" />

               ..............

                <LinearLayout
                    android:layout_height="0dp"
                    android:layout_weight="1"
                    android:gravity="bottom"
                    android:layout_width="match_parent">

                    <TextView
                        android:layout_width="match_parent"
                        android:layout_height="wrap_content"
                        android:height="50dp"
                        android:background="#b11"
                        android:gravity="center"
                        android:text="继续拖动查看图文详情"
                        android:textColor="#000" />

                </LinearLayout>
            </LinearLayout>

        </com.baoyunlong.view.pulluptoloadmore.MyScrollView>

        <com.baoyunlong.view.pulluptoloadmore.MyScrollView
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:fillViewport="true">

            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:gravity="center"
                android:orientation="vertical">


                <ImageView
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:src="@drawable/a1" />

                <ImageView
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:src="@drawable/a3" />

                .........


            </LinearLayout>

        </com.baoyunlong.view.pulluptoloadmore.MyScrollView>

    </com.baoyunlong.view.pulluptoloadmore.PullUpToLoadMore>

</RelativeLayout>
代码:
  1. public class PullUpToLoadMore extends ViewGroup {  
  2.   
  3.     public PullUpToLoadMore(Context context) {  
  4.         super(context);  
  5.     }  
  6.   
  7.     public PullUpToLoadMore(Context context, AttributeSet attrs) {  
  8.         super(context, attrs);  
  9.     }  
  10.   
  11.     public PullUpToLoadMore(Context context, AttributeSet attrs, int defStyleAttr) {  
  12.         super(context, attrs, defStyleAttr);  
  13.     }  
  14.   
  15.      
  16.   
  17.     @Override  
  18.     protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {  
  19.         super.onMeasure(widthMeasureSpec, heightMeasureSpec);  
  20.         measureChildren(widthMeasureSpec, heightMeasureSpec);  
  21.     }  
  22.   
  23.     @Override  
  24.     protected void onLayout(boolean changed, int l, int t, int r, int b) {  
  25.         int childCount = getChildCount();  
  26.         int childTop = t;  
  27.           
  28.         for (int i = 0; i < childCount; i++) {  
  29.             View child = getChildAt(i);  
  30.             child.layout(l, childTop, r, childTop + child.getMeasuredHeight());  
  31.             childTop += child.getMeasuredHeight();  
  32.         }  
  33.           
  34.     }  
  35. }  
public class PullUpToLoadMore extends ViewGroup {

    public PullUpToLoadMore(Context context) {
        super(context);
    }

    public PullUpToLoadMore(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public PullUpToLoadMore(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

   

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        measureChildren(widthMeasureSpec, heightMeasureSpec);
    }

    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        int childCount = getChildCount();
        int childTop = t;
        
        for (int i = 0; i < childCount; i++) {
            View child = getChildAt(i);
            child.layout(l, childTop, r, childTop + child.getMeasuredHeight());
            childTop += child.getMeasuredHeight();
        }
        
    }
}
2、处理滑动事件 
      规则如下 :
      (1)、当处于第一屏时 第一个ScrollView已经滑动到底部并且滑动方向是往上滑动,这个时候滑动事件应该交给父view处理也就是拦截事件让onInterceptTouchEvent返回true.然后父view通过scrollBy()方法滚动,显示出第二个scrollView。
      (2)、当处于第二屏时 第二个ScrollView已经滑动到顶部并且滑动方向是往下滑动,这个时候滑动事件交给父view处理,根据滑动事件显示出第一个ScrollView。
      (3)、当手指离开屏幕时,根据滑动速度来决定是回弹到第一个ScrollView还是第二个ScrollView,通过VelocityTracker来获取滑动速度。
3、一些细节的处理
        (1)、如果仔细看观察淘宝的实现效果你会发现,当你滑动到刚刚看到 “继续拖动,查看图文详情”的时候,手指抬起,然后再按下重新向上拖动你会发现,第二页并不会划出来,而是停留在了“继续拖动,查看图文详情”的底部,京东的效果也是一样。这样用户体验不太好,我们来优化一下。其实通过查看ScrollView的源码可以看出来,这是因为ScrollView类的onTouchEvent方法的默认实现,调用了parent.requestDisallowInterceptTouchEvent(true)方法 阻止了我们拦截事件,导致我们父view的onInterceptTouchEvent方法无法执行,也就拦截不到事件,拦截不到事件我们的onTouchEvent就无法执行,onTouchEvent无法执行,我们写在onTouchEvent里面的滚动逻辑就执行不到了,导致了上面我们看到的划不动的效果。解决方法就是,我们需要重写dispatchTouchEvent()方法,防止子view干扰我们,这样我们滑动的时候就可以一气呵成了。代码如下:
  1. @Override  
  2.     public boolean dispatchTouchEvent(MotionEvent ev) {  
  3.         //防止子View禁止父view拦截事件  
  4.         this.requestDisallowInterceptTouchEvent(false);  
  5.         return super.dispatchTouchEvent(ev);  
  6.     }  
@Override
    public boolean dispatchTouchEvent(MotionEvent ev) {
        //防止子View禁止父view拦截事件
        this.requestDisallowInterceptTouchEvent(false);
        return super.dispatchTouchEvent(ev);
    }
      (2)、监听ScrollView滑动事件的问题
          ScrollView没有提供滚动事件的监听方法,也就没法判断是否滚动到了顶部,或者底部,这里我们继承ScrollView 自己实现滚动事件监听。
  1. /** 
  2.  * Created by baoyunlong on 16/6/8. 
  3.  */  
  4. public class MyScrollView extends ScrollView {  
  5.     private static String TAG=MyScrollView.class.getName();  
  6.   
  7.     public void setScrollListener(ScrollListener scrollListener) {  
  8.         this.mScrollListener = scrollListener;  
  9.     }  
  10.   
  11.     private ScrollListener mScrollListener;  
  12.   
  13.     public MyScrollView(Context context) {  
  14.         super(context);  
  15.     }  
  16.   
  17.     public MyScrollView(Context context, AttributeSet attrs) {  
  18.         super(context, attrs);  
  19.     }  
  20.   
  21.     public MyScrollView(Context context, AttributeSet attrs, int defStyleAttr) {  
  22.         super(context, attrs, defStyleAttr);  
  23.     }  
  24.   
  25.     @Override  
  26.     public boolean onTouchEvent(MotionEvent ev) {  
  27.   
  28.         switch (ev.getAction()){  
  29.             case MotionEvent.ACTION_MOVE:  
  30.   
  31.                 if(mScrollListener!=null){  
  32.                     int contentHeight=getChildAt(0).getHeight();  
  33.                     int scrollHeight=getHeight();  
  34.   
  35.                     int scrollY=getScrollY();  
  36.                     mScrollListener.onScroll(scrollY);  
  37.   
  38.                     if(scrollY+scrollHeight>=contentHeight||contentHeight<=scrollHeight){  
  39.                         mScrollListener.onScrollToBottom();  
  40.                     }else {  
  41.                         mScrollListener.notBottom();  
  42.                     }  
  43.   
  44.                     if(scrollY==0){  
  45.                         mScrollListener.onScrollToTop();  
  46.                     }  
  47.   
  48.                 }  
  49.   
  50.                 break;  
  51.         }  
  52.         boolean result=super.onTouchEvent(ev);  
  53.         requestDisallowInterceptTouchEvent(false);  
  54.   
  55.         return result;  
  56.     }  
  57.   
  58.     public interface ScrollListener{  
  59.         void onScrollToBottom();  
  60.         void onScrollToTop();  
  61.         void onScroll(int scrollY);  
  62.         void notBottom();  
  63.     }  
/**
 * Created by baoyunlong on 16/6/8.
 */
public class MyScrollView extends ScrollView {
    private static String TAG=MyScrollView.class.getName();

    public void setScrollListener(ScrollListener scrollListener) {
        this.mScrollListener = scrollListener;
    }

    private ScrollListener mScrollListener;

    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) {

        switch (ev.getAction()){
            case MotionEvent.ACTION_MOVE:

                if(mScrollListener!=null){
                    int contentHeight=getChildAt(0).getHeight();
                    int scrollHeight=getHeight();

                    int scrollY=getScrollY();
                    mScrollListener.onScroll(scrollY);

                    if(scrollY+scrollHeight>=contentHeight||contentHeight<=scrollHeight){
                        mScrollListener.onScrollToBottom();
                    }else {
                        mScrollListener.notBottom();
                    }

                    if(scrollY==0){
                        mScrollListener.onScrollToTop();
                    }

                }

                break;
        }
        boolean result=super.onTouchEvent(ev);
        requestDisallowInterceptTouchEvent(false);

        return result;
    }

    public interface ScrollListener{
        void onScrollToBottom();
        void onScrollToTop();
        void onScroll(int scrollY);
        void notBottom();
    }
4、完整代码如下
  1. /** 
  2.  * Created by baoyunlong on 16/6/8. 
  3.  */  
  4. public class PullUpToLoadMore extends ViewGroup {  
  5.     public static String TAG = PullUpToLoadMore.class.getName();  
  6.   
  7.     MyScrollView topScrollView, bottomScrollView;  
  8.     VelocityTracker velocityTracker = VelocityTracker.obtain();  
  9.     Scroller scroller = new Scroller(getContext());  
  10.   
  11.     int currPosition = 0;  
  12.     int position1Y;  
  13.     int lastY;  
  14.     public int scaledTouchSlop;//最小滑动距离  
  15.     int speed = 200;  
  16.     boolean isIntercept;  
  17.   
  18.     public boolean bottomScrollVIewIsInTop = false;  
  19.     public boolean topScrollViewIsBottom = false;  
  20.   
  21.     public PullUpToLoadMore(Context context) {  
  22.         super(context);  
  23.         init();  
  24.     }  
  25.   
  26.     public PullUpToLoadMore(Context context, AttributeSet attrs) {  
  27.         super(context, attrs);  
  28.         init();  
  29.     }  
  30.   
  31.     public PullUpToLoadMore(Context context, AttributeSet attrs, int defStyleAttr) {  
  32.         super(context, attrs, defStyleAttr);  
  33.         init();  
  34.     }  
  35.   
  36.     private void init() {  
  37.   
  38.         post(new Runnable() {  
  39.             @Override  
  40.             public void run() {  
  41.                 topScrollView = (MyScrollView) getChildAt(0);  
  42.                 bottomScrollView = (MyScrollView) getChildAt(1);  
  43.                 topScrollView.setScrollListener(new MyScrollView.ScrollListener() {  
  44.                     @Override  
  45.                     public void onScrollToBottom() {  
  46.                         topScrollViewIsBottom = true;  
  47.                     }  
  48.   
  49.                     @Override  
  50.                     public void onScrollToTop() {  
  51.   
  52.                     }  
  53.   
  54.                     @Override  
  55.                     public void onScroll(int scrollY) {  
  56.   
  57.                     }  
  58.   
  59.                     @Override  
  60.                     public void notBottom() {  
  61.                         topScrollViewIsBottom = false;  
  62.                     }  
  63.   
  64.                 });  
  65.   
  66.                 bottomScrollView.setScrollListener(new MyScrollView.ScrollListener() {  
  67.                     @Override  
  68.                     public void onScrollToBottom() {  
  69.   
  70.                     }  
  71.   
  72.                     @Override  
  73.                     public void onScrollToTop() {  
  74.   
  75.                     }  
  76.   
  77.                     @Override  
  78.                     public void onScroll(int scrollY) {  
  79.                         if (scrollY == 0) {  
  80.                             bottomScrollVIewIsInTop = true;  
  81.                         } else {  
  82.                             bottomScrollVIewIsInTop = false;  
  83.                         }  
  84.                     }  
  85.   
  86.                     @Override  
  87.                     public void notBottom() {  
  88.   
  89.                     }  
  90.                 });  
  91.   
  92.                 position1Y = topScrollView.getBottom();  
  93.   
  94.                 scaledTouchSlop = ViewConfiguration.get(getContext()).getScaledTouchSlop();  
  95.             }  
  96.         });  
  97.     }  
  98.   
  99.     @Override  
  100.     public boolean dispatchTouchEvent(MotionEvent ev) {  
  101.         //防止子View禁止父view拦截事件  
  102.         this.requestDisallowInterceptTouchEvent(false);  
  103.         return super.dispatchTouchEvent(ev);  
  104.     }  
  105.   
  106.     @Override  
  107.     public boolean onInterceptTouchEvent(MotionEvent ev) {  
  108.         int y = (int) ev.getY();  
  109.   
  110.         switch (ev.getAction()) {  
  111.             case MotionEvent.ACTION_DOWN:  
  112.                 lastY = y;  
  113.                 break;  
  114.             case MotionEvent.ACTION_MOVE:  
  115.                 //判断是否已经滚动到了底部  
  116.                 if (topScrollViewIsBottom) {  
  117.                     int dy = lastY - y;  
  118.   
  119.                     //判断是否是向上滑动和是否在第一屏  
  120.                     if (dy > 0 && currPosition == 0) {  
  121.                         if (dy >= scaledTouchSlop) {  
  122.                             isIntercept = true;//拦截事件  
  123.                             lastY=y;  
  124.                         }  
  125.                     }  
  126.                 }  
  127.   
  128.                 if (bottomScrollVIewIsInTop) {  
  129.                     int dy = lastY - y;  
  130.   
  131.                     //判断是否是向下滑动和是否在第二屏  
  132.                     if (dy < 0 && currPosition == 1) {  
  133.                         if (Math.abs(dy) >= scaledTouchSlop) {  
  134.                             isIntercept = true;  
  135.                         }  
  136.                     }  
  137.                 }  
  138.   
  139.                 break;  
  140.         }  
  141.         return isIntercept;  
  142.     }  
  143.   
  144.     @Override  
  145.     public boolean onTouchEvent(MotionEvent event) {  
  146.         int y = (int) event.getY();  
  147.         velocityTracker.addMovement(event);  
  148.   
  149.         switch (event.getAction()) {  
  150.             case MotionEvent.ACTION_MOVE:  
  151.                 int dy = lastY - y;  
  152.                 if (getScrollY() + dy < 0) {  
  153.                     dy = getScrollY() + dy + Math.abs(getScrollY() + dy);  
  154.                 }  
  155.   
  156.                 if (getScrollY() + dy + getHeight() > bottomScrollView.getBottom()) {  
  157.                     dy = dy - (getScrollY() + dy - (bottomScrollView.getBottom() - getHeight()));  
  158.                 }  
  159.                 scrollBy(0, dy);  
  160.                 break;  
  161.             case MotionEvent.ACTION_UP:  
  162.                 isIntercept = false;  
  163.   
  164.                 velocityTracker.computeCurrentVelocity(1000);  
  165.                 float yVelocity = velocityTracker.getYVelocity();  
  166.   
  167.                 if (currPosition == 0) {  
  168.                     if (yVelocity < 0 && yVelocity < -speed) {  
  169.                         smoothScroll(position1Y);  
  170.                         currPosition = 1;  
  171.                     } else {  
  172.                         smoothScroll(0);  
  173.                     }  
  174.                 } else {  
  175.                     if (yVelocity > 0 && yVelocity > speed) {  
  176.                         smoothScroll(0);  
  177.                         currPosition = 0;  
  178.                     } else {  
  179.                         smoothScroll(position1Y);  
  180.                     }  
  181.                 }  
  182.                 break;  
  183.         }  
  184.         lastY = y;  
  185.         return true;  
  186.     }  
  187.   
  188.     @Override  
  189.     protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {  
  190.         super.onMeasure(widthMeasureSpec, heightMeasureSpec);  
  191.         measureChildren(widthMeasureSpec, heightMeasureSpec);  
  192.     }  
  193.   
  194.     @Override  
  195.     protected void onLayout(boolean changed, int l, int t, int r, int b) {  
  196.         int childCount = getChildCount();  
  197.         int childTop = t;  
  198.         for (int i = 0; i < childCount; i++) {  
  199.             View child = getChildAt(i);  
  200.             child.layout(l, childTop, r, childTop + child.getMeasuredHeight());  
  201.             childTop += child.getMeasuredHeight();  
  202.         }  
  203.     }  
  204.   
  205.     //通过Scroller实现弹性滑动  
  206.     private void smoothScroll(int tartY) {  
  207.         int dy = tartY - getScrollY();  
  208.         scroller.startScroll(getScrollX(), getScrollY(), 0, dy);  
  209.         invalidate();  
  210.     }  
  211.   
  212.     @Override  
  213.     public void computeScroll() {  
  214.         if (scroller.computeScrollOffset()) {  
  215.             scrollTo(scroller.getCurrX(), scroller.getCurrY());  
  216.             postInvalidate();  
  217.         }  
  218.     }  
  219. }  
/**
 * Created by baoyunlong on 16/6/8.
 */
public class PullUpToLoadMore extends ViewGroup {
    public static String TAG = PullUpToLoadMore.class.getName();

    MyScrollView topScrollView, bottomScrollView;
    VelocityTracker velocityTracker = VelocityTracker.obtain();
    Scroller scroller = new Scroller(getContext());

    int currPosition = 0;
    int position1Y;
    int lastY;
    public int scaledTouchSlop;//最小滑动距离
    int speed = 200;
    boolean isIntercept;

    public boolean bottomScrollVIewIsInTop = false;
    public boolean topScrollViewIsBottom = false;

    public PullUpToLoadMore(Context context) {
        super(context);
        init();
    }

    public PullUpToLoadMore(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    public PullUpToLoadMore(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }

    private void init() {

        post(new Runnable() {
            @Override
            public void run() {
                topScrollView = (MyScrollView) getChildAt(0);
                bottomScrollView = (MyScrollView) getChildAt(1);
                topScrollView.setScrollListener(new MyScrollView.ScrollListener() {
                    @Override
                    public void onScrollToBottom() {
                        topScrollViewIsBottom = true;
                    }

                    @Override
                    public void onScrollToTop() {

                    }

                    @Override
                    public void onScroll(int scrollY) {

                    }

                    @Override
                    public void notBottom() {
                        topScrollViewIsBottom = false;
                    }

                });

                bottomScrollView.setScrollListener(new MyScrollView.ScrollListener() {
                    @Override
                    public void onScrollToBottom() {

                    }

                    @Override
                    public void onScrollToTop() {

                    }

                    @Override
                    public void onScroll(int scrollY) {
                        if (scrollY == 0) {
                            bottomScrollVIewIsInTop = true;
                        } else {
                            bottomScrollVIewIsInTop = false;
                        }
                    }

                    @Override
                    public void notBottom() {

                    }
                });

                position1Y = topScrollView.getBottom();

                scaledTouchSlop = ViewConfiguration.get(getContext()).getScaledTouchSlop();
            }
        });
    }

    @Override
    public boolean dispatchTouchEvent(MotionEvent ev) {
        //防止子View禁止父view拦截事件
        this.requestDisallowInterceptTouchEvent(false);
        return super.dispatchTouchEvent(ev);
    }

    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        int y = (int) ev.getY();

        switch (ev.getAction()) {
            case MotionEvent.ACTION_DOWN:
                lastY = y;
                break;
            case MotionEvent.ACTION_MOVE:
                //判断是否已经滚动到了底部
                if (topScrollViewIsBottom) {
                    int dy = lastY - y;

                    //判断是否是向上滑动和是否在第一屏
                    if (dy > 0 && currPosition == 0) {
                        if (dy >= scaledTouchSlop) {
                            isIntercept = true;//拦截事件
                            lastY=y;
                        }
                    }
                }

                if (bottomScrollVIewIsInTop) {
                    int dy = lastY - y;

                    //判断是否是向下滑动和是否在第二屏
                    if (dy < 0 && currPosition == 1) {
                        if (Math.abs(dy) >= scaledTouchSlop) {
                            isIntercept = true;
                        }
                    }
                }

                break;
        }
        return isIntercept;
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        int y = (int) event.getY();
        velocityTracker.addMovement(event);

        switch (event.getAction()) {
            case MotionEvent.ACTION_MOVE:
                int dy = lastY - y;
                if (getScrollY() + dy < 0) {
                    dy = getScrollY() + dy + Math.abs(getScrollY() + dy);
                }

                if (getScrollY() + dy + getHeight() > bottomScrollView.getBottom()) {
                    dy = dy - (getScrollY() + dy - (bottomScrollView.getBottom() - getHeight()));
                }
                scrollBy(0, dy);
                break;
            case MotionEvent.ACTION_UP:
                isIntercept = false;

                velocityTracker.computeCurrentVelocity(1000);
                float yVelocity = velocityTracker.getYVelocity();

                if (currPosition == 0) {
                    if (yVelocity < 0 && yVelocity < -speed) {
                        smoothScroll(position1Y);
                        currPosition = 1;
                    } else {
                        smoothScroll(0);
                    }
                } else {
                    if (yVelocity > 0 && yVelocity > speed) {
                        smoothScroll(0);
                        currPosition = 0;
                    } else {
                        smoothScroll(position1Y);
                    }
                }
                break;
        }
        lastY = y;
        return true;
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        measureChildren(widthMeasureSpec, heightMeasureSpec);
    }

    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        int childCount = getChildCount();
        int childTop = t;
        for (int i = 0; i < childCount; i++) {
            View child = getChildAt(i);
            child.layout(l, childTop, r, childTop + child.getMeasuredHeight());
            childTop += child.getMeasuredHeight();
        }
    }

    //通过Scroller实现弹性滑动
    private void smoothScroll(int tartY) {
        int dy = tartY - getScrollY();
        scroller.startScroll(getScrollX(), getScrollY(), 0, dy);
        invalidate();
    }

    @Override
    public void computeScroll() {
        if (scroller.computeScrollOffset()) {
            scrollTo(scroller.getCurrX(), scroller.getCurrY());
            postInvalidate();
        }
    }
}


四、源码

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值