拿来就可以用,带header view的ScrollView

预期效果

类似魅族便签下拉显示标题的效果,加入了显示隐藏的动画。

实现

1、OnLayout中获取第一个子view的高度

    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        super.onLayout(changed, l, t, r, b);
        mChildLayout = (ViewGroup) getChildAt(0);
        mTopChildView = mChildLayout.getChildAt(0);
        topChildHeight = mTopChildView.getMeasuredHeight();
        screenHeight = getMeasuredHeight();
        offsetDistance = topChildHeight - screenHeight;
        if (!mInited) {
            mInited = true;
            if (currentPage == PAGE_BOTTOM) {
                scrollTo(0, topChildHeight);
            }
        }
    }

2、dispatchTouchEvent中在ACTION_UP时,通过getscrollY()即当前滑动的距离与header View高度的比较,并设定一个阈值,当getscrollY()大于或小于该阈值时,显示或隐藏header view。

@Override
    public boolean dispatchTouchEvent(MotionEvent ev) {
        if (isInIgnoredView(ev)) {
            //往下传递
            Log.e(TAG, "dispatchTouchEvent>>传递事件");
            return super.dispatchTouchEvent(ev);
        } else {
            Log.e(TAG, "dispatchTouchEvent>>不传递事件");
            switch (ev.getAction()) {
                case MotionEvent.ACTION_DOWN:
                    isTouch = true;
                    downY = (int) ev.getY();
                    downTime = System.currentTimeMillis();
                    if (mScroller != null) {
                        mScroller.forceFinished(true);
                        mScroller = null;
                    }
                    break;
                case MotionEvent.ACTION_MOVE:

                    break;
                case MotionEvent.ACTION_UP:
                    isTouch = false;
                    upY = (int) ev.getY();
                    upTime = System.currentTimeMillis();
                    boolean isUpMove = upY - downY <= 0;//是否上划
                    //用户手指在屏幕上的时间
                    long duration = upTime - downTime;

                    //这里要确保点击事件不失效
                    //we force stop scroll when touch down
                    //in some case we need to finish scroll up or down
                    if (currentPage == PAGE_TOP) {
                        //下面的判断已经能确定用户是否往上滑
                        if (getScrollY() > offsetDistance) {
                            mScroller = new Scroller(mContext);
                            if (getScrollY() < (screenHeight * PERCENT + offsetDistance) && duration > TOUCH_DURATION) {
                                //基本可以无视
                                isPageChange = false;
                                scrollToTarget(PAGE_TOP);
                            } else if (getScrollY() > topChildHeight / 5) {
                                //切换到下界面 手势是上划且滑动的距离大于一定值
                                isPageChange = true;
                                scrollToTarget(PAGE_BOTTOM);

                            } else if (getScrollY() <= topChildHeight / 5) {
                                isPageChange = false;
                                scrollToTarget(PAGE_TOP);
                            } else if (getScrollY() > topChildHeight) {
                                isPageChange = true;
                                currentPage = PAGE_BOTTOM;
                            }
                            return false;
                        }
                    } else {
                        if (getScrollY() < topChildHeight) {
                            mScroller = new Scroller(mContext);
                            if (getScrollY() < topChildHeight / 2) {
                                //切换到上界面
                                isPageChange = true;
                                scrollToTarget(PAGE_TOP);
                            } else {
                                isPageChange = false;
                                scrollToTarget(PAGE_BOTTOM);
                            }
                            return false;
                        }
                    }

                    break;
            }
        }

        return super.dispatchTouchEvent(ev);
    }

3、header view设置粘性滑动(有没有更贴切的名字?) 即scrollview的滑动不跟随手指的滑动,假如设置的比值为0.4,那么手指滑动10个像素,实际scrollview只滑动了4个像素,类似下拉刷新的那种下拉吃力的感觉。实现方法很简单,在TouchEvent中,通过scrollBy()方法实现scrollview的滑动,并返回true,表示scrollview消费了该次事件。

  @Override
    public boolean onTouchEvent(MotionEvent ev) {
        if (isInIgnoredView(ev)) {
            Log.e(TAG, "onTouchEvent>>不消费事件");
            return false;
        } else {
            Log.e(TAG, "onTouchEvent>>消费事件");
            currentY = (int) ev.getY();
            switch (ev.getAction()) {
                case MotionEvent.ACTION_DOWN:
                    lastY = (int) ev.getY();
                    break;
                case MotionEvent.ACTION_MOVE:
                    int moveY = currentY - lastY;
                    lastY = currentY;
                    if (currentPage == PAGE_BOTTOM) {
                        if (getScrollY() <= topChildHeight) {
                            //下拉
                            scrollBy(0, (int) (-moveY * mFraction));
                            return true;
                        } else {
                            return super.onTouchEvent(ev);
                        }
                    } else {
                        return super.onTouchEvent(ev);
                    }
                case MotionEvent.ACTION_CANCEL:
                case MotionEvent.ACTION_UP:
                    break;
            }
            return super.onTouchEvent(ev);
        }
    }

4、动画。动画使用了属性动画,这里就不多介绍了。

效果图

gif太大..简书上传不了.
偷偷懒,移步github看效果

GitHub

github源码

欢迎star…欢迎吐槽…

    原文作者:tse1y
    原文地址: https://www.jianshu.com/p/a73dfdcbc02f
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞