欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Android仿材料设计实现京东上推隐藏头部

程序员文章站 2022-05-25 08:18:32
...

Android仿材料设计实现京东上推隐藏头部

最近写的一个项目的实现类似于京东商品的展示,不bb先上图

Android仿材料设计实现京东上推隐藏头部

  • 动画
  • 事件拦截
  • 对滑动的监听

动画

我这里是主要是使用了两个动画ObjectAnimator,就是让绿色区域上去,然后让下面的区域上来,注意这里有几点:

1.当我们下面滑动视图的第一个条目没有显示时,不让绿色出来;
2.当绿色的出来时,我们向上滑动滚动视图时就要让绿色上去,滑动区域也上来。

我这里加入了上拉加载和下拉刷新,所以也要注意两点:

1.当滚动试图的第一个条目可见且绿色可见是,下滑的事件给包裹的刷新控件;
2.当滚动的视图的第一个条码不可见且绿色不可见时,下滑的事件还是给滑动控件处理;

这里我使用的滑动控件是RecyclerView,因人而异

Android仿材料设计实现京东上推隐藏头部

布局

注意这里的下拉刷新上拉加载(我的小伙伴使用的02年的一个控件)我吓得眼泪都掉下来了,但是由于是属于app开源sdk多个项目在改,所以我只有在原有基础是改,大家可以使用新的,用过的应该比较清楚。

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <RelativeLayout
        android:id="@+id/rl_title"
        android:layout_width="match_parent"
        android:layout_height="150dp"
        android:background="@color/color_24cf5f">

        <TextView
            android:id="@+id/tv_title"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_centerHorizontal="true"
            android:text="我的积分" />

        <TextView
            android:id="@+id/tv_num"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_below="@+id/tv_title"
            android:layout_centerHorizontal="true"
            android:layout_marginTop="10dp"
            android:text="2.00" />
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:gravity="center_horizontal"
            android:layout_below="@+id/tv_num"
            android:orientation="horizontal"
            >
            <LinearLayout
                android:layout_width="wrap_content"
                android:background="@drawable/lb_hslib_shape_integralmall"
                android:paddingTop="2dp"
                android:paddingBottom="2dp"
                android:paddingLeft="10dp"
                android:paddingRight="10dp"
                android:id="@+id/ll_jfcj"
                android:layout_marginRight="20dp"
                android:layout_height="wrap_content">
                <TextView
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:text="积分抽奖"/>
            </LinearLayout>
            <LinearLayout
                android:layout_width="wrap_content"
                android:background="@drawable/lb_hslib_shape_integralmall"
                android:paddingTop="2dp"
                android:paddingBottom="2dp"
                android:paddingLeft="10dp"
                android:paddingRight="10dp"
                android:id="@+id/ll_zqjf"
                android:layout_height="wrap_content">
                <TextView
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:text="赚取积分"/>
            </LinearLayout>
        </LinearLayout>
    </RelativeLayout>
    <LinearLayout
        android:layout_width="match_parent"
        android:orientation="vertical"
        android:id="@+id/ll_content"
        android:layout_height="match_parent">
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="40dp"
            android:orientation="horizontal">
            <TextView
                android:layout_width="0dp"
                android:layout_height="match_parent"
                android:layout_weight="1"
                android:gravity="center"
                android:id="@+id/tv_fenlei"
                android:text="分类"/>
            <TextView
                android:layout_width="0dp"
                android:layout_height="match_parent"
                android:layout_weight="1"
                android:gravity="center"
                android:id="@+id/tv_redian"
                android:text="热点"/>
        </LinearLayout>
        <RelativeLayout
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:layout_weight="1">
            <commonlib.view.AbPullToRefreshView
                android:id="@+id/act_integramall_ablv"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:orientation="vertical">

                <commonlib.view.HsTopRecyclerView
                    android:id="@+id/act_integramall_recyclerview"
                    android:layout_width="match_parent"
                    android:layout_height="match_parent"
                    android:scrollbars="none" />

                <commonlib.view.EmptyLayout
                    android:id="@+id/act_integramall_error_layout"
                    android:layout_width="match_parent"
                    android:layout_height="match_parent"
                    android:background="@color/color_ffffff"
                    android:visibility="gone" />

            </commonlib.view.AbPullToRefreshView>
            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:id="@+id/ll_masking"
                android:orientation="vertical"
                android:visibility="gone"
                android:clickable="true"
                android:background="#66000000"/>
        </RelativeLayout>
    </LinearLayout>
</LinearLayout>

刷新控件

这是那个刷新控件(不需要可以忽略)
public class AbPullToRefreshView extends LinearLayout {

    /**
     * 日志标记.
     */
    private static final String TAG = "AbPullToRefreshView";

    /**
     * 上下文.
     */
    private Context mContext = null;

    /**
     * 下拉刷新的开关.
     */
    private boolean mEnablePullRefresh = true;

    /**
     * 加载更多的开关.
     */
    private boolean mEnableLoadMore = true;

    /**
     * y上一次保存的.
     */
    private int mLastMotionY;

    /**
     * header view.
     */
    private AbListViewHeader mHeaderView;

    /**
     * footer view.
     */
    private AbListViewFooter mFooterView;

    /**
     * list or grid.
     */
    private AdapterView<?> mAdapterView;

    /**
     * 是否允许在list或grid模式下没有子项时刷新和加载
     */
    private boolean mEnablePullAndLoadWithNoChild = true;

    /**
     * Scrollview.
     */
    private ScrollView mScrollView;

    /**
     * RecyclerView.
     */
    private RecyclerView mRecyclerView;

    /**
     * 对recyclerview上的头部视图的拦截
     * 见HsIntegralMallActivity界面
     */

    private boolean topVisibility=true;
    /**
     * header view 高度.
     */
    private int mHeaderViewHeight;

    /**
     * footer view 高度.
     */
    private int mFooterViewHeight;

    /**
     * 滑动状态.
     */
    private int mPullState;

    /**
     * 上滑动作.
     */
    private static final int PULL_UP_STATE = 0;

    /**
     * 下拉动作.
     */
    private static final int PULL_DOWN_STATE = 1;

    /**
     * 上一次的数量.
     */
    private int mCount = 0;

    /**
     * 是否还有数据.
     */
    private boolean isAll = false;

    /**
     * 正在下拉刷新.
     */
    public boolean mPullRefreshing = false;

    /**
     * 正在加载更多.
     */
    public boolean mPullLoading = false;

    /**
     * Footer加载更多监听器.
     */
    private OnFooterLoadListener mOnFooterLoadListener;

    /**
     * Header下拉刷新监听器.
     */
    private OnHeaderRefreshListener mOnHeaderRefreshListener;

    /**
     * 用于控制延时收回Header和Footer
     */
    private Timer mTimer;

    /**
     * UI线程的句柄
     */
    private Handler mHandler;

    /**
     * 构造.
     *
     * @param context the context
     * @param attrs   the attrs
     */
    public AbPullToRefreshView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init(context);
    }

    /**
     * 构造.
     *
     * @param context the context
     */
    public AbPullToRefreshView(Context context) {
        super(context);
        init(context);
    }

    /**
     * 初始化View.
     *
     * @param context the context
     */
    private void init(Context context) {
        mContext = context;

        mHandler = new Handler(context.getMainLooper());
        mTimer = new Timer();

        // 增加HeaderView
        addHeaderView();
    }

    /**
     * add HeaderView.
     */
    private void addHeaderView() {
        mHeaderView = new AbListViewHeader(mContext);
        mHeaderViewHeight = mHeaderView.getHeaderHeight();
        mHeaderView.setGravity(Gravity.BOTTOM);
//        mHeaderView.setBackgroundColor(Color.TRANSPARENT);

        LayoutParams params = new LayoutParams(LayoutParams.MATCH_PARENT,
                mHeaderViewHeight);
        // 设置topMargin的值为负的header View高度,即将其隐藏在最上方
        params.topMargin = -(mHeaderViewHeight);
        addView(mHeaderView, params);

    }

    /**
     * add FooterView.
     */
    private void addFooterView() {

        mFooterView = new AbListViewFooter(mContext);
        mFooterViewHeight = mFooterView.getFooterHeight();
//        mFooterView.setBackgroundColor(Color.TRANSPARENT);

        LayoutParams params = new LayoutParams(LayoutParams.MATCH_PARENT,
                mFooterViewHeight);
        addView(mFooterView, params);
    }

    /**
     * 在此添加footer view保证添加到linearlayout中的最后.
     */
    @Override
    protected void onFinishInflate() {
        super.onFinishInflate();
        addFooterView();
        initContentAdapterView();
    }

    /**
     * init AdapterView like ListView, GridView and so on; or init ScrollView.
     */
    private void initContentAdapterView() {
        int count = getChildCount();
        if (count < 3) {
            throw new IllegalArgumentException(
                    "this layout must contain 3 child views,and AdapterView or ScrollView must in the second position!");
        }
        View view = null;
        for (int i = 0; i < count - 1; ++i) {
            view = getChildAt(i);
            if (view instanceof AdapterView<?>) {
                mAdapterView = (AdapterView<?>) view;
            }
            if (view instanceof ScrollView) {
                // finish later
                mScrollView = (ScrollView) view;
            }
            if(view instanceof RecyclerView){
                mRecyclerView= (RecyclerView) view;
            }
        }
        if (mAdapterView == null && mScrollView == null&&mRecyclerView==null) {
            throw new IllegalArgumentException(
                    "must contain a AdapterView or ScrollView in this layout!");
        }
    }

    /*
     * (non-Javadoc)
     *
     * @see
     * android.view.ViewGroup#onInterceptTouchEvent(android.view.MotionEvent)
     */
    @Override
    public boolean onInterceptTouchEvent(MotionEvent e) {
        int y = (int) e.getRawY();
        switch (e.getAction()) {
            case MotionEvent.ACTION_DOWN:
                // 首先拦截down事件,记录y坐标
                mLastMotionY = y;
                break;
            case MotionEvent.ACTION_MOVE:
                // deltaY > 0 是向下运动,< 0是向上运动
                int deltaY = y - mLastMotionY;
                if (isRefreshViewScroll(deltaY)) {
                    return true;
                }
                break;
            case MotionEvent.ACTION_UP:
            case MotionEvent.ACTION_CANCEL:
                break;
        }
        return false;
    }

    /*
     * 如果在onInterceptTouchEvent()方法中没有拦截(即onInterceptTouchEvent()方法中 return
     * false)则由PullToRefreshView 的子View来处理;否则由下面的方法来处理(即由PullToRefreshView自己来处理)
     */
    /*
     * (non-Javadoc)
     * 
     * @see android.view.View#onTouchEvent(android.view.MotionEvent)
     */
    @Override
    public boolean onTouchEvent(MotionEvent event) {

        int y = (int) event.getRawY();
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                // onInterceptTouchEvent已经记录 mLastMotionY = y;
                break;
            case MotionEvent.ACTION_MOVE:
                int deltaY = y - mLastMotionY;
                if (mPullState == PULL_DOWN_STATE) {
                    // 执行下拉
                    headerPrepareToRefresh(deltaY);
                } else if (mPullState == PULL_UP_STATE) {
                    // 执行上拉
                    footerPrepareToRefresh(deltaY);
                }
                mLastMotionY = y;
                break;
            case MotionEvent.ACTION_UP:
            case MotionEvent.ACTION_CANCEL:
                int topMargin = getHeaderTopMargin();
                if (mPullState == PULL_DOWN_STATE) {
                    if (topMargin >= 0) {
                        // 开始刷新
                        headerRefreshing();
                    } else {
                        // 还没有执行刷新,重新隐藏
                        setHeaderTopMargin(-mHeaderViewHeight);
                    }
                } else if (mPullState == PULL_UP_STATE) {
                    if (Math.abs(topMargin) >= mHeaderViewHeight
                            + mFooterViewHeight) {
                        // 开始执行footer 刷新
                        footerLoading();
                    } else {
                        // 还没有执行刷新,重新隐藏
                        setHeaderTopMargin(-mHeaderViewHeight);
                    }
                }
                break;
        }
        return super.onTouchEvent(event);
    }

    /**
     * 判断滑动方向,和是否响应事件.
     *
     * @param deltaY deltaY > 0 是向下运动,< 0是向上运动
     * @return true, if is refresh view scroll
     */
    private boolean isRefreshViewScroll(int deltaY) {

        if (mPullRefreshing || mPullLoading) {
            return false;
        }
        // 对于ListView和GridView
        if (mAdapterView != null) {
            // 子view(ListView or GridView)滑动到最顶端
            if (deltaY > 0) {
                // 判断是否禁用下拉刷新操作
                if (!mEnablePullRefresh) {
                    return false;
                }
                View child = mAdapterView.getChildAt(0);
                if (!mEnablePullAndLoadWithNoChild && child == null) {
                    // 如果mAdapterView中没有数据,不拦截
                    return false;
                }
                if (child == null)
                    child = mAdapterView;
                if (mAdapterView.getFirstVisiblePosition() == 0
                        && child.getTop() == 0) {
                    mPullState = PULL_DOWN_STATE;
                    return true;
                }
                int top = child.getTop();
                int padding = mAdapterView.getPaddingTop();
                if (mAdapterView.getFirstVisiblePosition() == 0
                        && Math.abs(top - padding) <= 11) {// 这里之前用3可以判断,但现在不行,还没找到原因
                    mPullState = PULL_DOWN_STATE;
                    return true;
                }

            } else if (deltaY < -10) {
                // 判断是否禁用上拉加载更多操作
                if (!mEnableLoadMore) {
                    return false;
                }
                View lastChild = mAdapterView.getChildAt(mAdapterView
                        .getChildCount() - 1);
                if (lastChild == null) {
                    // 如果mAdapterView中没有数据,不拦截
                    return false;
                }
                // 最后一个子view的Bottom小于父View的高度说明mAdapterView的数据没有填满父view,
                // 等于父View的高度说明mAdapterView已经滑动到最后
                if (lastChild.getBottom() <= getHeight()
                        && mAdapterView.getLastVisiblePosition() == mAdapterView
                        .getCount() - 1) {
                    mPullState = PULL_UP_STATE;
                    return true;
                }
            }
        }
        // 对于ScrollView
        if (mScrollView != null) {

            // 子scroll view滑动到最顶端
            View child = mScrollView.getChildAt(0);
            if (deltaY > 0 && mScrollView.getScrollY() == 0) {
                mPullState = PULL_DOWN_STATE;
                // 判断是否禁用下拉刷新操作
                return mEnablePullRefresh;
            } else if (deltaY < 0
                    && child.getMeasuredHeight() <= getHeight()
                    + mScrollView.getScrollY()) {
                // 判断是否禁用上拉加载更多操作
                if (!mEnableLoadMore) {
                    return false;
                }
                mPullState = PULL_UP_STATE;
                return true;
            }
        }
        if(mRecyclerView!=null){
            LinearLayoutManager manager= (LinearLayoutManager) mRecyclerView.getLayoutManager();
            if (deltaY > 0) {
                // 判断是否禁用下拉刷新操作
                if (!mEnablePullRefresh) {
                    return false;
                }
                if(!topVisibility){
                    return false;
                }
                View child = mRecyclerView.getChildAt(0);
                if (!mEnablePullAndLoadWithNoChild && child == null) {
                    // 如果mAdapterView中没有数据,不拦截
                    return false;
                }

                if (manager.findFirstCompletelyVisibleItemPosition() == 0) {
                    mPullState = PULL_DOWN_STATE;
                    return true;
                }

            }else if (deltaY < -10) {
            // 判断是否禁用上拉加载更多操作
                if (!mEnableLoadMore) {
                    return false;
                }
                View lastChild = mRecyclerView.getChildAt(mRecyclerView
                        .getChildCount() - 1);
                if (lastChild == null) {
                    // 如果mAdapterView中没有数据,不拦截
                    return false;
                }
                if (mRecyclerView.computeVerticalScrollExtent() + mRecyclerView.computeVerticalScrollOffset()
                        >= mRecyclerView.computeVerticalScrollRange()){
                    mPullState = PULL_UP_STATE;
                    return true;
                }
            }
        }

        return false;
    }

    /**
     * header 准备刷新,手指移动过程,还没有释放.
     *
     * @param deltaY 手指滑动的距离
     */
    private void headerPrepareToRefresh(int deltaY) {
        if (mPullRefreshing || mPullLoading) {
            return;
        }

        int newTopMargin = updateHeaderViewTopMargin(deltaY);
        // 当header view的topMargin>=0时,说明header view完全显示出来了 ,修改header view 的提示状态
        if (newTopMargin >= 0
                && mHeaderView.getState() != AbListViewHeader.STATE_REFRESHING) {
            // 提示松开刷新
            mHeaderView.setState(AbListViewHeader.STATE_READY);

        } else if (newTopMargin < 0 && newTopMargin > -mHeaderViewHeight) {
            // 提示下拉刷新
            mHeaderView.setState(AbListViewHeader.STATE_NORMAL);
        }
    }

    /**
     * footer 准备刷新,手指移动过程,还没有释放 移动footer view高度同样和移动header view
     * 高度是一样,都是通过修改header view的topmargin的值来达到.
     *
     * @param deltaY 手指滑动的距离
     */
    private void footerPrepareToRefresh(int deltaY) {
        if (mPullRefreshing || mPullLoading) {
            return;
        }
        int newTopMargin = updateHeaderViewTopMargin(deltaY);
        // 如果header view topMargin 的绝对值大于或等于header + footer 的高度
        // 说明footer view 完全显示出来了,修改footer view 的提示状态
        if (Math.abs(newTopMargin) >= (mHeaderViewHeight + mFooterViewHeight)
                && mFooterView.getState() != AbListViewFooter.STATE_LOADING) {
            mFooterView.setState(AbListViewFooter.STATE_READY);
        } else if (Math.abs(newTopMargin) < (mHeaderViewHeight + mFooterViewHeight)) {
            mFooterView.setState(AbListViewFooter.STATE_LOADING);
        }
    }

    /**
     * 修改Header view top margin的值.
     *
     * @param deltaY the delta y
     * @return the int
     */
    private int updateHeaderViewTopMargin(int deltaY) {
        LayoutParams params = (LayoutParams) mHeaderView.getLayoutParams();
        float newTopMargin = params.topMargin + deltaY * 0.3f;
        // 这里对上拉做一下限制,因为当前上拉后然后不释放手指直接下拉,会把下拉刷新给触发了
        // 表示如果是在上拉后一段距离,然后直接下拉
        if (deltaY > 0 && mPullState == PULL_UP_STATE
                && Math.abs(params.topMargin) <= mHeaderViewHeight) {
            return params.topMargin;
        }
        // 同样地,对下拉做一下限制,避免出现跟上拉操作时一样的bug
        if (deltaY < 0 && mPullState == PULL_DOWN_STATE
                && Math.abs(params.topMargin) >= mHeaderViewHeight) {
            return params.topMargin;
        }
        params.topMargin = (int) newTopMargin;
        mHeaderView.setLayoutParams(params);
        invalidate();
        return params.topMargin;
    }

    /**
     * 下拉刷新.
     */
    public void headerRefreshing() {
        mPullRefreshing = true;
        mHeaderView.setState(AbListViewHeader.STATE_REFRESHING);
        setHeaderTopMargin(0);
        if (mOnHeaderRefreshListener != null) {

            // lzd 网络判断
            if (AbAppUtil.isNetworkAvailable()) {
                mOnHeaderRefreshListener.onHeaderRefresh(this);
            } else {
                onHeaderRefreshFinish();
                ToastUtils.showToast(HstationInstance.C().getString(R.string.lianbi_hslib_netfail_refresh));
            }

        }
    }

    /**
     * 加载更多.
     */
    private void footerLoading() {
        mPullLoading = true;
        int top = mHeaderViewHeight + mFooterViewHeight;
        setHeaderTopMargin(-top);
        if (mOnFooterLoadListener != null) {
            // lzd 网络判断
            if (AbAppUtil.isNetworkAvailable()) {
                mOnFooterLoadListener.onFooterLoad(this);
            } else {
                onFooterLoadFinish(true);
                ToastUtils.showToast(HstationInstance.C().getString(R.string.lianbi_hslib_netfail_refresh));
            }
        }
    }

    /**
     * 设置header view 的topMargin的值.
     *
     * @param topMargin the new header top margin
     */
    private void setHeaderTopMargin(int topMargin) {
        LayoutParams params = (LayoutParams) mHeaderView.getLayoutParams();
        params.topMargin = topMargin;
        mHeaderView.setLayoutParams(params);
        invalidate();
    }

    /**
     * header view 完成更新后恢复初始状态.
     */
    public void onHeaderRefreshFinish() {
        setHeaderTopMargin(-mHeaderViewHeight);
        mHeaderView.setState(AbListViewHeader.STATE_READY);
        if (mAdapterView != null) {
            mCount = mAdapterView.getCount();
            // 判断有没有数据
            if (mCount > 0) {
                mFooterView.setState(AbListViewFooter.STATE_READY);
            } else {
                mFooterView.setState(AbListViewFooter.STATE_EMPTY);
            }
        } else {
            mFooterView.setState(AbListViewFooter.STATE_READY);
        }
        mPullRefreshing = false;
    }

    /**
     * footer view 完成更新后恢复初始状态.
     */
    public void onFooterLoadFinish() {
        setHeaderTopMargin(-mHeaderViewHeight);
        mHeaderView.setState(AbListViewHeader.STATE_NORMAL);
        if (mAdapterView != null) {
            int countNew = mAdapterView.getCount();
            // 判断有没有更多数据了
            if (countNew > mCount) {
                mFooterView.setState(AbListViewFooter.STATE_READY);
                mPullLoading = false;
                mCount = countNew;
            } else {
                mFooterView.setState(AbListViewFooter.STATE_NO);
                int top = mHeaderViewHeight + mFooterViewHeight;
                setHeaderTopMargin(-top);
                mHandler.postDelayed(new Runnable() {
                    @Override
                    public void run() {
                        setHeaderTopMargin(-mHeaderViewHeight);
                        isAll = true;
                        mPullLoading = false;
                    }
                }, 2000);
            }
        } else {
            mFooterView.setState(AbListViewFooter.STATE_READY);
            mPullLoading = false;
        }
    }



    /**
     *  咨询带广告没有更多数据
     */
    public void setNodata(){
        mFooterView.setState(AbListViewFooter.STATE_NO);
        int top = mHeaderViewHeight + mFooterViewHeight;
        setHeaderTopMargin(-top);
        mHandler.postDelayed(new Runnable() {
            @Override
            public void run() {
                setHeaderTopMargin(-mHeaderViewHeight);
                isAll = true;
                mPullLoading = false;
            }
        }, 2000);
    }

    /**
     * footer view 完成更新后恢复初始状态.
     */
    public void onFooterLoadFinish(boolean hasnext) {
        setHeaderTopMargin(-mHeaderViewHeight);
        mHeaderView.setState(AbListViewHeader.STATE_NORMAL);
        if (mAdapterView != null && !hasnext) {
            int countNew = mAdapterView.getCount();
            // 判断有没有更多数据了
            if (countNew > mCount) {
                mFooterView.setState(AbListViewFooter.STATE_READY);
                mPullLoading = false;
                mCount = countNew;
            } else {
                mFooterView.setState(AbListViewFooter.STATE_NO);
                int top = mHeaderViewHeight + mFooterViewHeight;
                setHeaderTopMargin(-top);
                mHandler.postDelayed(new Runnable() {
                    @Override
                    public void run() {
                        setHeaderTopMargin(-mHeaderViewHeight);
                        isAll = true;
                        mPullLoading = false;
                    }
                }, 2000);
            }
        } else {
            if (!hasnext) {
                mFooterView.setState(AbListViewFooter.STATE_NO);
                int top = mHeaderViewHeight + mFooterViewHeight;
                setHeaderTopMargin(-top);
                mHandler.postDelayed(new Runnable() {
                    @Override
                    public void run() {
                        setHeaderTopMargin(-mHeaderViewHeight);
                        isAll = true;
                        mPullLoading = false;
                    }
                }, 2000);
            } else {
                mFooterView.setState(AbListViewFooter.STATE_READY);
                mPullLoading = false;
            }
        }
    }

    /**
     * 获取当前header view 的topMargin.
     *
     * @return the header top margin
     */
    private int getHeaderTopMargin() {
        LayoutParams params = (LayoutParams) mHeaderView.getLayoutParams();
        return params.topMargin;
    }

    /**
     * 设置下拉刷新的监听器.
     *
     * @param headerRefreshListener the new on header refresh listener
     */
    public void setOnHeaderRefreshListener(
            OnHeaderRefreshListener headerRefreshListener) {
        mOnHeaderRefreshListener = headerRefreshListener;
    }

    /**
     * 设置加载更多的监听器.
     *
     * @param footerLoadListener the new on footer load listener
     */
    public void setOnFooterLoadListener(OnFooterLoadListener footerLoadListener) {
        mOnFooterLoadListener = footerLoadListener;
    }

    /**
     * 打开或者关闭下拉刷新功能.
     *
     * @param enable 开关标记
     */
    public void setPullRefreshEnable(boolean enable) {
        mEnablePullRefresh = enable;
    }

    /**
     * 打开或者关闭加载更多功能.
     *
     * @param enable 开关标记
     */
    public void setLoadMoreEnable(boolean enable) {
        mEnableLoadMore = enable;
    }

    /**
     * 下拉刷新是打开的吗.
     *
     * @return true, if is enable pull refresh
     */
    public boolean isEnablePullRefresh() {
        return mEnablePullRefresh;
    }

    /**
     * 加载更多是打开的吗.
     *
     * @return true, if is enable load more
     */
    public boolean isEnableLoadMore() {
        return mEnableLoadMore;
    }

    /**
     * 设置是否允许没有子控件时刷新/加载
     *
     * @param mEnablePullAndLoadWithNoChild
     */
    public void setmEnablePullAndLoadWithNoChild(
            boolean mEnablePullAndLoadWithNoChild) {
        this.mEnablePullAndLoadWithNoChild = mEnablePullAndLoadWithNoChild;
    }

    /**
     * 描述:获取Header View.
     *
     * @return the header view
     */
    public AbListViewHeader getHeaderView() {
        return mHeaderView;
    }

    /**
     * 描述:获取Footer View.
     *
     * @return the footer view
     */
    public AbListViewFooter getFooterView() {
        return mFooterView;
    }

    /**
     * 描述:获取Header ProgressBar,用于设置自定义样式.
     *
     * @return the header progress bar
     */
    public GifView getHeaderProgressBar() {
        return mHeaderView.getHeaderProgressBar();
    }

    /**
     * 描述:获取Footer ProgressBar,用于设置自定义样式.
     *
     * @return the footer progress bar
     */
    public GifView getFooterProgressBar() {
        return mFooterView.getFooterProgressBar();
    }

    public interface OnFooterLoadListener {

        /**
         * On footer load.
         *
         * @param view the view
         */
        void onFooterLoad(AbPullToRefreshView view);
    }

    public interface OnHeaderRefreshListener {

        /**
         * On header refresh.
         *
         * @param view the view
         */
        void onHeaderRefresh(AbPullToRefreshView view);
    }

    /**
     * 对recyclerview上的头部空间可见性的设置
     * @param topVisibility
     */
    public void setTopVisibility(boolean topVisibility) {
        this.topVisibility = topVisibility;
    }
}

RecyclerView

public class HsTopRecyclerView extends RecyclerView {
    private float mpoint,mcurent;
    private TestTouchEvent testTouchEvent;

    public void setTestTouchEvent(TestTouchEvent testTouchEvent) {
        this.testTouchEvent = testTouchEvent;
    }

    public HsTopRecyclerView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
    }

    @Override
    public boolean onTouchEvent(MotionEvent e) {
        switch (e.getAction()){
            case MotionEvent.ACTION_DOWN:
                mpoint=e.getRawY();
                break;
            case MotionEvent.ACTION_MOVE:
                mcurent=e.getRawY();
                if(mcurent-mpoint>4){
                    if(testTouchEvent!=null){
                        testTouchEvent.event(true);
                    }
                }else {
                    if(testTouchEvent!=null){
                        testTouchEvent.event(false);
                    }
                }
                break;
        }
        return super.onTouchEvent(e);
    }
    public interface TestTouchEvent{
        void event(boolean isDown);
    }
}

Activity

由于有封装,请*发挥

public class HsIntegralMallActivity extends BaseActivity {
    private AbPullToRefreshView mAddPlatformAblv;
    private HsTopRecyclerView recyclerView;
    private RecyclerView popu_recyclerview;
    private EmptyLayout emptyLayout;
    private RelativeLayout relativeLayout;
    private HsIntegralMallAdapter adapter;
    private LinearLayout ll_content, popu_ll_content, ll_masking,ll_zqjf,ll_jfcj;
    private ObjectAnimator animatorGone, animatorShow, animatorUp, animatorDown;
    private boolean visibility = true;
    private ViewTreeObserver vto;
    private GridLayoutManager layoutManager;
    private int wheight, statusBarHeight1, height;
    private PopupWindow popupWindow;
    private TextView tv_fenlei, tv_redian, tv_title;
    private ArrayList<String> listTest;
    private HsEasyRecyclerAdapterHs<String> popu_adapter;
    private boolean sortClick = false, classClick = false;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.lb_hslib_integramall_activity);
        initView();
        initEvent();
        initData();
        initData(true);
        initPopuWindow();
    }

    /**
     * 初始化控件
     */
    private void initView() {
        mAddPlatformAblv = findView(R.id.act_integramall_ablv);
        recyclerView = findView(R.id.act_integramall_recyclerview);
        emptyLayout = findView(R.id.act_integramall_error_layout);
        relativeLayout = findView(R.id.rl_title);
        ll_content = findView(R.id.ll_content);
        tv_fenlei = findView(R.id.tv_fenlei);
        tv_redian = findView(R.id.tv_redian);
        tv_title = findView(R.id.tv_title);
        ll_masking = findView(R.id.ll_masking);
        ll_zqjf=findView(R.id.ll_zqjf);
        ll_jfcj=findView(R.id.ll_jfcj);
    }

    /**
     * 初始化监听
     */
    private void initEvent() {
        mAddPlatformAblv.setOnHeaderRefreshListener(new AbPullToRefreshView.OnHeaderRefreshListener() {
            @Override
            public void onHeaderRefresh(AbPullToRefreshView view) {
                initData(true);
            }
        });

        mAddPlatformAblv.setOnFooterLoadListener(new AbPullToRefreshView.OnFooterLoadListener() {
            @Override
            public void onFooterLoad(AbPullToRefreshView view) {
                initData(false);
            }
        });
        vto = relativeLayout.getViewTreeObserver();
        vto.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
            @Override
            public void onGlobalLayout() {
                relativeLayout.getViewTreeObserver().removeGlobalOnLayoutListener(this);
                height = relativeLayout.getHeight();
                initAnimator(relativeLayout, ll_content);
            }
        });
        WindowManager wm = this.getWindowManager();
        wheight = wm.getDefaultDisplay().getHeight();

        statusBarHeight1 = -1;
        //获取status_bar_height资源的ID
        int resourceId = getResources().getIdentifier("status_bar_height", "dimen", "android");
        if (resourceId > 0) {
            //根据资源ID获取响应的尺寸值
            statusBarHeight1 = getResources().getDimensionPixelSize(resourceId);
        }
        mAddPlatformAblv.setLoadMoreEnable(true);
        mAddPlatformAblv.setPullRefreshEnable(true);
        recyclerView.setTestTouchEvent(new HsTopRecyclerView.TestTouchEvent() {
            @Override
            public void event(boolean isDown) {
                if (isDown && layoutManager.findFirstCompletelyVisibleItemPosition() == 0 && !visibility) {
                    if (!animatorShow.isRunning() && !animatorDown.isRunning() && !animatorGone.isRunning() && !animatorUp.isRunning()) {
                        animatorShow.start();
                        animatorDown.start();
                    }
                } else if (!isDown && visibility && !animatorGone.isRunning() && !animatorUp.isRunning() && !animatorShow.isRunning() && !animatorDown.isRunning()) {
                    animatorGone.start();
                    animatorUp.start();
                }
            }
        });
        recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
            @Override
            public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
                super.onScrollStateChanged(recyclerView, newState);
                if (newState == RecyclerView.SCROLL_STATE_IDLE) {
                    //不可以下滚
                    if (!recyclerView.canScrollVertically(-1) && !visibility) {
                        animatorShow.start();
                        animatorDown.start();
                    }
                }
            }
        });
        tv_fenlei.setOnClickListener(this);
        tv_redian.setOnClickListener(this);
        ll_masking.setOnClickListener(this);
        tv_title.setOnClickListener(this);
        ll_zqjf.setOnClickListener(this);
        ll_jfcj.setOnClickListener(this);
    }

    @Override
    protected void onChildClick(View view) {
        super.onChildClick(view);
        Intent intent;
        if (view == tv_fenlei) {
            if (classClick) {
                popupWindow.dismiss();
                classClick=false;
            }else {
                if (popupWindow.isShowing()) {
                    initPopuData(0);
                    sortClick=false;
                }
                if (!popupWindow.isShowing()) {
                    initPopuData(0);
                    popupWindow.showAsDropDown(view);
                    ll_masking.setVisibility(View.VISIBLE);
                }
                classClick=true;
            }

        } else if (view == tv_redian) {
            if(sortClick){
                popupWindow.dismiss();
                sortClick=false;
            }else {
                if (popupWindow.isShowing()) {
                    initPopuData(1);
                    classClick=false;
                }
                if (!popupWindow.isShowing()) {
                    initPopuData(1);
                    popupWindow.showAsDropDown(view);
                    ll_masking.setVisibility(View.VISIBLE);
                }
                sortClick=true;
            }

        } else if (view == ll_masking) {
            popupWindow.dismiss();
        } else if (view == tv_title) {
            intent=new Intent();
            intent.setClass(getWeakContext(),HsWinningRecordingActivity.class);
            startActivity(intent);
        }else if(view==ll_zqjf){
            intent=new Intent();
            intent.setClass(getWeakContext(),HsGetIntegralActivity.class);
            startActivity(intent);
        }else if(view==ll_jfcj){
            intent=new Intent();
            intent.setClass(getWeakContext(),HsLotteryWebActivity.class);
            startActivity(intent);
        }
    }

    /**
     * 初始化动画
     *
     * @param rl
     * @param ll
     */
    public void initAnimator(RelativeLayout rl, LinearLayout ll) {
        animatorGone = ObjectAnimator.ofFloat(rl, "translationY", 0, -height);
        animatorGone.setDuration(200);
        animatorShow = ObjectAnimator.ofFloat(rl, "translationY", -height, 0);
        animatorShow.setDuration(200);
        animatorUp = ObjectAnimator.ofFloat(ll, "translationY", 0, -height);
        animatorUp.setDuration(200);
        animatorDown = ObjectAnimator.ofFloat(ll, "translationY", -height, 0);
        animatorDown.setDuration(200);
        Animator.AnimatorListener listener = new Animator.AnimatorListener() {
            @Override
            public void onAnimationStart(Animator animation) {
            }

            @Override
            public void onAnimationEnd(Animator animation) {
                visibility = !visibility;
                mAddPlatformAblv.setTopVisibility(visibility);
                if (visibility) {
                    layoutManager.scrollToPositionWithOffset(0, 0);
                }
            }

            @Override
            public void onAnimationCancel(Animator animation) {
            }

            @Override
            public void onAnimationRepeat(Animator animation) {
            }
        };
        animatorShow.addListener(listener);
        animatorGone.addListener(listener);
    }

    /**
     * 初始化数据
     */
    private void initData() {
        ll_content.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, wheight - ScreenUtils.dp2px(getWeakContext(), 48) - statusBarHeight1));
        recyclerView.setLayoutManager(layoutManager = new GridLayoutManager(getWeakContext(), 2));
        adapter = new HsIntegralMallAdapter(getWeakContext());
        popu_adapter = new HsEasyRecyclerAdapterHs<String>(getWeakContext(), R.layout.lb_hslib_integrapopuwindow_item) {
            TextView poputv_title;
            @Override
            public void onBind(HsBaseViewHolder holder, int position) {
                poputv_title = holder.get(R.id.tv_content);
                poputv_title.setText(get(position));
                System.out.println("初始化了");
                poputv_title.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        if (popupWindow.isShowing()) {
                            popupWindow.dismiss();
                            Toast.makeText(getWeakContext(), "点击了", Toast.LENGTH_SHORT).show();
                        }
                    }
                });
            }
        };
        recyclerView.setAdapter(adapter);
    }

    /**
     * 下载
     *
     * @param isRefresh
     */
    private void initData(boolean isRefresh) {
        ArrayList<Records> list = new ArrayList<>();
        for (int i = 0; i < 10; i++) {
            list.add(new Records());
        }
        adapter.addAll(list);
        AbPullHide.hideRefreshView(isRefresh, mAddPlatformAblv);
    }

    /**
     * 初始化弹窗
     */
    private void initPopuWindow() {
        View view = LayoutInflater.from(getWeakContext()).inflate(R.layout.lb_hslib_integrallmall_popu_layout, null);
        popu_recyclerview = (RecyclerView) view.findViewById(R.id.rv);
        popu_recyclerview.setLayoutManager(new LinearLayoutManager(getWeakContext()));
        popu_recyclerview.setAdapter(popu_adapter);
        popu_ll_content = (LinearLayout) view.findViewById(R.id.ll_content);
        popupWindow = new PopupWindow(view, LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT);
        popupWindow.setBackgroundDrawable(new ColorDrawable(0xffffffff));
        popupWindow.setOnDismissListener(new PopupWindow.OnDismissListener() {
            @Override
            public void onDismiss() {
                ll_masking.setVisibility(View.GONE);
                sortClick=false;
                classClick=false;
            }
        });
    }

    /**
     * 初始化弹窗数据
     */
    private void initPopuData(int type) {
        listTest = new ArrayList<>();
        popu_adapter.clear();
        switch (type) {
            case 0:
                for (int i = 0; i < 7; i++) {
                    listTest.add("测试" + i);
                }
                popu_adapter.addAll(listTest);
                if (listTest.size() > 6) {
                    popu_ll_content.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, 300));
                } else {
                    popu_ll_content.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT));
                }

                break;
            case 1:
                for (int i = 0; i < 2; i++) {
                    listTest.add("测试" + i);
                }
                popu_adapter.addAll(listTest);
                if (listTest.size() > 6) {
                    popu_ll_content.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, 300));
                } else {
                    popu_ll_content.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT));
                }

                break;
        }
    }

}

事件拦截

主要就是对数据以及是否第一个条码可见来判断

 if(mRecyclerView!=null){
            LinearLayoutManager manager= (LinearLayoutManager) mRecyclerView.getLayoutManager();
            if (deltaY > 0) {
                // 判断是否禁用下拉刷新操作
                if (!mEnablePullRefresh) {
                    return false;
                }
                if(!topVisibility){
                    return false;
                }
                View child = mRecyclerView.getChildAt(0);
                if (!mEnablePullAndLoadWithNoChild && child == null) {
                    // 如果mAdapterView中没有数据,不拦截
                    return false;
                }

                if (manager.findFirstCompletelyVisibleItemPosition() == 0) {
                    mPullState = PULL_DOWN_STATE;
                    return true;
                }

            }else if (deltaY < -10) {
            // 判断是否禁用上拉加载更多操作
                if (!mEnableLoadMore) {
                    return false;
                }
                View lastChild = mRecyclerView.getChildAt(mRecyclerView
                        .getChildCount() - 1);
                if (lastChild == null) {
                    // 如果mAdapterView中没有数据,不拦截
                    return false;
                }
                if (mRecyclerView.computeVerticalScrollExtent() + mRecyclerView.computeVerticalScrollOffset()
                        >= mRecyclerView.computeVerticalScrollRange()){
                    mPullState = PULL_UP_STATE;
                    return true;
                }
            }

对滑动的监听

recyclerView.setTestTouchEvent(new HsTopRecyclerView.TestTouchEvent() {
            @Override
            public void event(boolean isDown) {
                if (isDown && layoutManager.findFirstCompletelyVisibleItemPosition() == 0 && !visibility) {
                    if (!animatorShow.isRunning() && !animatorDown.isRunning() && !animatorGone.isRunning() && !animatorUp.isRunning()) {
                        animatorShow.start();
                        animatorDown.start();
                    }
                } else if (!isDown && visibility && !animatorGone.isRunning() && !animatorUp.isRunning() && !animatorShow.isRunning() && !animatorDown.isRunning()) {
                    animatorGone.start();
                    animatorUp.start();
                }
            }
        });
        recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
            @Override
            public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
                super.onScrollStateChanged(recyclerView, newState);
                if (newState == RecyclerView.SCROLL_STATE_IDLE) {
                    //不可以下滚
                    if (!recyclerView.canScrollVertically(-1) && !visibility) {
                        animatorShow.start();
                        animatorDown.start();
                    }
                }
            }
        });

效果在最上面,抠脚来的不喜勿喷