美文网首页具体自定义控件
Android 自定义 上拉加载容器

Android 自定义 上拉加载容器

作者: 小白彡 | 来源:发表于2020-03-13 17:39 被阅读0次

    App中下拉刷新和上拉加载是很常见的功能,网上也有很多第三方库可以用,为了尽快完成项目,一般都是集成别人的库快速完成功能, 但有时候产品脑洞比较大 ,用别人的库又没那么灵活改起来也麻烦, 就只能自己来了。。。。。
    下面看一下效果:


    WeChat_20200313173628.gif

    自定义还是挺麻烦的,不过也比较有意思,完成这个需要先了解几个知识点:
    1.自定义ViewGroup
    2.Scroller
    3.事件分发体系。
    下面开始简单的实现一下:
    1.自定义ReboundLinearLayout 继承自 RelativeLayout 这个ViewGroup内部放需要上拉加载的Recyclerview

    public class ReboundLinearLayout extends RelativeLayout {
    

    2.由于事件传递的时候RecyclerView会把事件全部消耗完,所以要在ReboundLinearLayout的onInterceptTouchEvent中判断需要拦截的事件, 这里的思路是:如果RecyclerView已经滑动到最底部,就可以进行上拉加载了,这时候就可以拦截手指的向上滑动事件:

    @Override
        public boolean onInterceptTouchEvent(MotionEvent ev) {
            if(isSlideToBottom(reboundRecyclerView)){
                switch (ev.getAction()){
                    case MotionEvent.ACTION_DOWN:
                        startY = ev.getY();
                        break;
                    case MotionEvent.ACTION_MOVE:
                        endY = ev.getY();
                        if(endY - startY >= 0){
                            return false;
                        }else if(endY - startY < 0){
                            return true;
                        }
                        break;
                    case MotionEvent.ACTION_UP:
                        break;
                    default:
                        break;
                }
            }else{
                return false;
            }
            return false;
        }
    

    3.在拦截完事件后,我们在onTouchEvent中进行事件的处理,当然就是使用scroller来将RecyclerView进行移动了:

    @Override
        public boolean onTouchEvent(MotionEvent event) {
            switch (event.getAction()){
                case MotionEvent.ACTION_DOWN:
                case MotionEvent.ACTION_MOVE:
                    scrollEndY = event.getY();
                    if(startY - scrollEndY <= SizeUtils.dp2px(scrollHeight)){
                        scrollTo(0, (int) (startY - scrollEndY));
                    }
                    break;
                case MotionEvent.ACTION_UP:
                    mScroller.startScroll(0, getScrollY(),0, -getScrollY(),300);
                    invalidate();
                    if(onRefreshListenner != null){
                        onRefreshListenner.onRefresh();
                    }
                    break;
                default:
                    break;
            }
            return true;
        }
    

    这样就可以实现简单的上拉加载了,加个刷新监听 ,在刷新的时候请求数据,就完成啦。。。
    下面贴一下代码

    public class ReboundLinearLayout extends RelativeLayout {
    
        private RecyclerView reboundRecyclerView;
        //判断滑动方向
        private float startY;
        private float endY;
    
        private float scrollEndY;
    
        private Scroller mScroller;
        //最大拉动距离
        private int scrollHeight = 80;
    
        private OnRefreshListenner onRefreshListenner;
    
        public ReboundLinearLayout(Context context) {
            super(context);
        }
    
        public ReboundLinearLayout(Context context, AttributeSet attrs) {
            super(context, attrs);
            mScroller = new Scroller(context);
        }
    
        public ReboundLinearLayout(Context context, AttributeSet attrs, int defStyleAttr) {
            super(context, attrs, defStyleAttr);
        }
    
        @Override
        public boolean onInterceptTouchEvent(MotionEvent ev) {
            if(isSlideToBottom(reboundRecyclerView)){
                switch (ev.getAction()){
                    case MotionEvent.ACTION_DOWN:
                        startY = ev.getY();
                        break;
                    case MotionEvent.ACTION_MOVE:
                        endY = ev.getY();
                        if(endY - startY >= 0){
                            return false;
                        }else if(endY - startY < 0){
                            return true;
                        }
                        break;
                    case MotionEvent.ACTION_UP:
                        break;
                    default:
                        break;
                }
            }else{
                return false;
            }
            return false;
        }
    
        @Override
        public boolean onTouchEvent(MotionEvent event) {
            switch (event.getAction()){
                case MotionEvent.ACTION_DOWN:
                case MotionEvent.ACTION_MOVE:
                    scrollEndY = event.getY();
                    if(startY - scrollEndY <= SizeUtils.dp2px(scrollHeight)){
                        scrollTo(0, (int) (startY - scrollEndY));
                    }
                    break;
                case MotionEvent.ACTION_UP:
                    mScroller.startScroll(0, getScrollY(),0, -getScrollY(),300);
                    invalidate();
                    if(onRefreshListenner != null){
                        onRefreshListenner.onRefresh();
                    }
                    break;
                default:
                    break;
            }
            return true;
        }
    
        @Override
        protected void onFinishInflate() {
            super.onFinishInflate();
            reboundRecyclerView = (RecyclerView) getChildAt(0);
        }
    
        public static boolean isSlideToBottom(RecyclerView recyclerView) {
            if (recyclerView == null) return false;
            if (recyclerView.computeVerticalScrollExtent() + recyclerView.computeVerticalScrollOffset()
                    >= recyclerView.computeVerticalScrollRange())
                return true;
            return false;
        }
    
        @Override
        public void computeScroll() {
            super.computeScroll();
            //第二步
            if(mScroller.computeScrollOffset()){
                //第三步
                scrollTo(mScroller.getCurrX(),mScroller.getCurrY());
                invalidate();
            }
        }
    
        public void setOnRefreshListenner(OnRefreshListenner onRefreshListenner) {
            this.onRefreshListenner = onRefreshListenner;
        }
    
        public interface OnRefreshListenner{
            void onRefresh();
        }
    }
    

    结束。

    相关文章

      网友评论

        本文标题:Android 自定义 上拉加载容器

        本文链接:https://www.haomeiwen.com/subject/mtkjshtx.html