Android scrollview How to Monitor Slide Status

  • 2021-11-14 07:01:40
  • OfStack

ScrollView

The scrolling process of the view is actually constantly modifying the origin coordinates. When the finger touches, ScrollView will temporarily intercept the touch event and use a timer. If no finger movement event occurs after the timer reaches the point, ScrollView sends tracking events to the clicked subView; If a moving event occurs after the timer reaches the point, ScrollView cancels tracking's self-initiated scroll.

First of all, let's talk about monitoring the sliding event of NestedScrollView under 1.

If you use


nestedScrollView.setOnScrollChangeListener(new View.OnScrollChangeListener() {
      @Override
      public void onScrollChange(View v, int scrollX, int scrollY, int oldScrollX, int oldScrollY) {
 
      }
    });

This method is used in API > It can only be used at 23:00. How to solve it? We can define an ScrollView ourselves


public class MyScrollView extends NestedScrollView {
   private OnScrollChanged mOnScrollChanged;
  public MyScrollView(Context context) {
    this(context, null);
  }
  public MyScrollView(Context context, AttributeSet attributeSet) {
    this(context, attributeSet, 0);
  }
  public MyScrollView(Context context, AttributeSet attrs, int defStyleAttr) {
    super(context, attrs, defStyleAttr);
  }
  @Override
  protected void onScrollChanged(int l, int t, int oldl, int oldt) {
    super.onScrollChanged(l, t, oldl, oldt);
    if (mOnScrollChanged != null) {
      mOnScrollChanged.onScroll(l, t, oldl, oldt);
    }
  }
  public void setOnScrollChanged(OnScrollChanged onScrollChanged) {
    this.mOnScrollChanged = onScrollChanged;
  }
  public interface OnScrollChanged {
    void onScroll(int l, int t, int oldl, int oldt);
  }
}

In this way, we can monitor sliding events by implementing onScrollChanged (), in which sliding distance can be monitored, so we can do many things well;

But now there is a requirement that "when sliding, hide a floating box on the side, and if not sliding, the floating box will be displayed", so it is necessary to monitor the sliding state. Unlike recyclerview1, scrollview can monitor sliding state.

The following is my one implementation scheme, which is implemented through CountDownTimer

Add methods to the onScrollChanged interface just now


public interface OnScrollChanged {
    void onScroll(int l, int t, int oldl, int oldt);
 
    void onTouch(boolean isDown);
  }

Then override the onTouchEvent method


@Override
  public boolean onTouchEvent(MotionEvent ev) {
      switch (ev.getAction()) {
      case MotionEvent.ACTION_UP:
      case MotionEvent.ACTION_CANCEL:
        if (mOnScrollChanged != null) {
          mOnScrollChanged.onTouch(false);
        }
        break;
      case MotionEvent.ACTION_DOWN:
      case MotionEvent.ACTION_MOVE:
        if (mOnScrollChanged != null) {
          mOnScrollChanged.onTouch(true);
        }
        break;
    }
    return super.onTouchEvent(ev);
  }

Here, isDown=true represents a pressed or sliding state, corresponding to ACTION_DOWN and ACTION_MOVE, and fale represents ACTION_UP and ACTION_CANCEL

Use this custom scrollerview below


// Static state 
private final static int SCROLL_STATE_IDLE = 1;
// Drag or inertial sliding state 
private final static int SCROLL_STATE_SCROLL = 2;
 
// Judge whether it is a drag state 
boolean isDragState = false;
 
int currentState = SCROLL_STATE_IDLE;
 
// Used here 100ms To judge whether it is already in a static state, 100ms After the end, it proves to be a static state 
private CountDownTimer scrollCountTimer = new CountDownTimer(100, 1) {
    @Override
    public void onTick(long millisUntilFinished) {
 
    }
 
    @Override
    public void onFinish() {
      setScrollState(SCROLL_STATE_IDLE);
    }
};
 
private void initScrollView() {
    scrollView.setOnScrollChanged(new MyScrollView.OnScrollChanged() {
      @Override
      public void onScroll(int l, int t, int oldl, int oldt) {
        if (isDragState) {// Drag status is handled separately, and scrolling status monitoring is no longer performed 
          return;
        }
        // When sliding, cancel the countdown first and set the sliding state 
        scrollCountTimer.cancel();
        if(currentState != SCROLL_STATE_SCROLL) {
          setScrollState(SCROLL_STATE_SCROLL);
        }
        scrollCountTimer.start();
      }
 
      @Override
      public void onTouch(boolean isDown) {
        isDragState = isDown;
        // Here, I default the pressed state to the scrolled state, of course, you can define it separately 
        if (isDown) {
          scrollCountTimer.cancel();
          setScrollState(SCROLL_STATE_SCROLL);
        } else {
          scrollCountTimer.start();
        }
      }
});
// Finally, remember that when the page is destroyed, cancel Drop timer

Summarize


Related articles: