实现监听NestedScrollView拖拽、惯性滑动、滑动停止、滑动到顶部和底部

运行实时监听日志:

实现监听NestedScrollView拖拽、惯性滑动、滑动停止、滑动到顶部和底部_第1张图片

因为在开发中经常会需要在滚动的各种状态下处理一些UI界面功能,但是系统又没有提供实时监听拖拽、惯性滑动、滑动停止、滑动到顶部和底部等功能。那怎么办,只能自己去实现这些功能。

  • 滚动的几种状态
    /**
     * 滚动状态
     */
    public enum ScrollState{
        DRAG,      // 拖拽中
        SCROLLING, // 正在滚动
        IDLE       // 已停止
    }
  • 回调方法
 public interface AddScrollChangeListener{
        /**
         * 滚动监听
         * @param scrollX
         * @param scrollY
         * @param oldScrollX
         * @param oldScrollY
         */
        void onScrollChange( int scrollX, int scrollY, int oldScrollX, int oldScrollY);


        /**
         * 滚动状态
         *
         * @param state
         */
        void onScrollState(ScrollState state);
    }

重写 public boolean onTouchEvent(MotionEvent ev)实现 监听拖拽、监听惯性滑动、监听滑动停止

  • 监听拖拽
  • 监听惯性滑动
  • 监听滑动停止

    @Override
    public boolean onTouchEvent(MotionEvent ev) {
        switch (ev.getAction()){
            case MotionEvent.ACTION_DOWN:
            case MotionEvent.ACTION_MOVE:
                isStart = false ;
                LogUtils.LOG_V("[NewNestedScrollView]->DRAG 拖拽中");
                if (addScrollChangeListener!=null){
                    addScrollChangeListener.onScrollState(ScrollState.DRAG);
                }
                break;

            case MotionEvent.ACTION_CANCEL:
            case MotionEvent.ACTION_OUTSIDE:
            case MotionEvent.ACTION_UP:
                isStart = true ;
                start();
                break;
        }
        return super.onTouchEvent(ev);
    }



  /**
     *
     * 开始计算是否停止还是正在滚性滑动
     *
     */
    private void start() {
        new  Thread(new Runnable() {
            @Override
            public void run() {
                while (isStart){
                    if ((System.currentTimeMillis() - lastTime)>50){
                        int newScrollY = getScrollY();
                        lastTime = System.currentTimeMillis();
                        if (newScrollY - lastScrollY == 0){
                            isStart = false ;
                            LogUtils.LOG_V("[NewNestedScrollView]->IDLE 停止滚动");

                            handler.post(new Runnable() {
                                @Override
                                public void run() {
                                    if (addScrollChangeListener!=null){
                                        addScrollChangeListener.onScrollState(ScrollState.IDLE);
                                    }
                                }
                            });
                        }else {
                            handler.post(new Runnable() {
                                @Override
                                public void run() {
                                    LogUtils.LOG_V("[NewNestedScrollView]->SCROLLING 正在滚动中");
                                    if (isStart&&addScrollChangeListener!=null){
                                        addScrollChangeListener.onScrollState(ScrollState.SCROLLING );
                                    }
                                }
                            });
                        }
                        lastScrollY = newScrollY;
                    }
                }
            }
        }).start();
    }


  • 监听滑动到顶部

    @Override
    public void onScrollChange(NestedScrollView v, int scrollX, int scrollY, int oldScrollX, int oldScrollY) {
        if (getScrollY()<=0){
            LogUtils.LOG_V("[NewNestedScrollView]->onScrollChange = top");
            top = true ;
        }else {
            top = false ;
        }
    }


  • 监听底部 (首先需要知道整个滚动内容的高度和当前滚动控件view的高度)从写onMeasure()测量测试高度

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        totalHeight = 0 ;
        int count = getChildCount();
        for (int i =0 ;i < count ;i++){
            View view = getChildAt(i);
            totalHeight += view.getMeasuredHeight();
        }
        viewHeight = getHeight() ;
    }


    @Override
    public void onScrollChange(NestedScrollView v, int scrollX, int scrollY, int oldScrollX, int oldScrollY) {
        if (totalHeight>viewHeight && (totalHeight - viewHeight) == scrollY){
            LogUtils.LOG_V("[NewNestedScrollView]->onScrollChange = bottom");
            bottom = true ;
        }else {
            bottom = false ;
        }
    }


完整代码列子

import android.content.Context;
import android.os.Handler;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.core.widget.NestedScrollView;


public class NewNestedScrollView extends NestedScrollView implements NestedScrollView.OnScrollChangeListener {


    /**
     *
     */
    private AddScrollChangeListener addScrollChangeListener;


    /**
     * 滚动状态
     */
    public enum ScrollState{
        DRAG,      // 拖拽中
        SCROLLING, // 正在滚动
        IDLE       // 已停止
    }

    /**
     *
     * 记录上一次滑动
     *
     */
    private int lastScrollY ;
    /**
     */
    private boolean isStart = false ;
    /**
     * 上一次记录的时间
     */
    private long lastTime ;


    private Handler handler;
    /**
     * 整個滾動内容高度
     *
     */
    public int totalHeight = 0 ;

    /**
     *
     * 当前view的高度
     *
     */
    public int viewHeight = 0 ;

    /**
     * 是否滚动到底了
     */
    private boolean bottom = false;

    /**
     * 是否滚动在顶部
     *
     * @param context
     */
    private boolean top = false ;


    public NewNestedScrollView(@NonNull Context context) {
        this(context,null);
    }

    public NewNestedScrollView(@NonNull Context context, @Nullable AttributeSet attrs) {
        this(context, attrs,0);
    }

    public NewNestedScrollView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        setOnScrollChangeListener(this);
        handler = new Handler(context.getMainLooper());
    }


    @Override
    public void onScrollChange(NestedScrollView v, int scrollX, int scrollY, int oldScrollX, int oldScrollY) {
        /*实时滚动回调*/
        if (addScrollChangeListener!=null){
            addScrollChangeListener.onScrollChange( scrollX,  scrollY,  oldScrollX,  oldScrollY);
        }

        if (totalHeight>viewHeight && (totalHeight - viewHeight) == scrollY){
            LogUtils.LOG_V("[NewNestedScrollView]->onScrollChange = bottom");
            bottom = true ;
        }else {
            bottom = false ;
        }

        if (getScrollY()<=0){
            LogUtils.LOG_V("[NewNestedScrollView]->onScrollChange = top");
            top = true ;
        }else {
            top = false ;
        }
    }



    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        totalHeight = 0 ;
        int count = getChildCount();
        for (int i =0 ;i < count ;i++){
            View view = getChildAt(i);
            totalHeight += view.getMeasuredHeight();
        }
        viewHeight = getHeight() ;
    }




    /**
     * 是否动到底
     * @return
     */
    public boolean isBottom(){
        return bottom;
    }



    /**
     * 是否滚动到了 顶部
     *
     * @return
     */
    public boolean isTop(){
        return top;
    }



    @Override
    public boolean onTouchEvent(MotionEvent ev) {
        switch (ev.getAction()){
            case MotionEvent.ACTION_DOWN:
            case MotionEvent.ACTION_MOVE:
                isStart = false ;
                LogUtils.LOG_V("[NewNestedScrollView]->DRAG 拖拽中");
                if (addScrollChangeListener!=null){
                    addScrollChangeListener.onScrollState(ScrollState.DRAG);
                }
                break;

            case MotionEvent.ACTION_CANCEL:
            case MotionEvent.ACTION_OUTSIDE:
            case MotionEvent.ACTION_UP:
                isStart = true ;
                start();
                break;
        }
        return super.onTouchEvent(ev);
    }


    /**
     *
     * 开始计算是否停止还是正在滚性滑动
     *
     */
    private void start() {
        new  Thread(new Runnable() {
            @Override
            public void run() {
                /**
                 * 表示已停止
                 */
                while (isStart){
                    if ((System.currentTimeMillis() - lastTime)>50){
                        int newScrollY = getScrollY();
                        lastTime = System.currentTimeMillis();
                        if (newScrollY - lastScrollY == 0){
                            isStart = false ;
                            LogUtils.LOG_V("[NewNestedScrollView]->IDLE 停止滚动");

                            handler.post(new Runnable() {
                                @Override
                                public void run() {
                                    if (addScrollChangeListener!=null){
                                        addScrollChangeListener.onScrollState(ScrollState.IDLE);
                                    }
                                }
                            });
                        }else {
                            handler.post(new Runnable() {
                                @Override
                                public void run() {
                                    LogUtils.LOG_V("[NewNestedScrollView]->SCROLLING 正在滚动中");
                                    if (isStart&&addScrollChangeListener!=null){
                                        addScrollChangeListener.onScrollState(ScrollState.SCROLLING );
                                    }
                                }
                            });
                        }
                        lastScrollY = newScrollY;
                    }
                }
            }
        }).start();
    }



    /**
     * 设置监听
     *
     * @param addScrollChangeListener
     * @return
     */
    public NewNestedScrollView addScrollChangeListener(AddScrollChangeListener addScrollChangeListener) {
        this.addScrollChangeListener =  addScrollChangeListener;
        return this ;
    }


    public interface AddScrollChangeListener{
        /**
         * 滚动监听
         * @param scrollX
         * @param scrollY
         * @param oldScrollX
         * @param oldScrollY
         */
        void onScrollChange( int scrollX, int scrollY, int oldScrollX, int oldScrollY);


        /**
         * 滚动状态
         *
         * @param state
         */
        void onScrollState(ScrollState state);
    }
}

如何使用


    private class NewOnScroll implements NewNestedScrollView.AddScrollChangeListener {

        @Override
        public void onScrollChange(int scrollX, int scrollY, int oldScrollX, int oldScrollY) {

        }

        @Override
        public void onScrollState(NewNestedScrollView.ScrollState state) {
            MainActivity activity = (MainActivity) getActivity();
            switch (state){
                case DRAG:
                case SCROLLING:
                    activity.anim(Util.screenWidth()-Util.dp2Px(30));
                    activity.alpha(0.4f);
                    break;
                case IDLE:
                    activity.anim(Util.screenWidth()-Util.dp2Px(70));
                    activity.alpha(1f);
                    break;
            }
        }
    }

你可能感兴趣的:(学习笔记,工作笔记,java,android)