View event system one (touch, gesture, slide)

1. View basic touch, gesture, sliding events

View is an abstraction of the space of all interface layers.
The origin of the Android screen coordinate system is in the upper left corner, and the left, right, top, and bottom properties of the View are relative to the coordinates of its parent View.


1. MotionEvent and TouchSlop

  1. MotionEvent

    After the finger touches the screen, the typical event type:

    • ACTION_DOWN: The finger just touches the screen;
    • ACTION_MOVE: Move your finger on the screen;
    • Aciton_UP: The moment the finger is released on the screen

    Generally speaking, the normal behavior of touching the screen will trigger a series of events, such as

    • Release immediately after clicking on the screen, event sequence: DOWN -> UP
    • Click on the screen, slide for a while and release, event sequence: DOWN -> MOVE -> …. -> MOVE -> UP

    MotionEvent provides two sets of methods for obtaining coordinates relative to the current View and coordinates relative to the screen origin:

    • getX()/ getY(): Get the x and y coordinates relative to the upper left corner of the current View.
    • getRawX()/ getRawY: Get the x and y coordinates relative to the screen origin.
  2. TouchSlop

    • TouchSlop is the minimum distance that the system can recognize as sliding, which is obtained by the following code:
      ViewConfiguration.get(getApplicationContext()).getScaledTouchSlop();

    • When processing swipes, you can use this to filter out swipes that are too small to improve user experience.

2. VelocityTracker、GestureDetector 和 Scroller

  1. VelocityTrackerSpeed ​​tracker, which can track the speed of the current event:

    @Override
    public boolean onTouch(View v, MotionEvent event) {
        if (velocityTracker1 == null) {
            velocityTracker1 = VelocityTracker.obtain();
        }
        velocityTracker1.addMovement(event);
        //参数单位:毫秒
        velocityTracker1.computeCurrentVelocity(1000);
        int xVelocity = (int) velocityTracker1.getXVelocity();
        int yVelocity = (int) velocityTracker1.getYVelocity();
        Log.d(TAG, "velocity:" + xVelocity + ", " + yVelocity);
        return true;
    }

    When appropriate, it needs to be recycled:

    protected void onDestroy() {
        velocityTracker.clear();
        velocityTracker.recycle();
        super.onDestroy();
    }
  2. GestureDetector

    • Create an GestureDetectorobject and implement an interface.

      GestureDetector gestureDetector = new GestureDetector(new GestureDetector.OnGestureListener() {
          @Override
          public boolean onDown(MotionEvent e) {
              Log.d(TAG, "由ACTION_DOWN 触发 "+e.getAction());
              return false;
          }
      
          @Override
          public void onShowPress(MotionEvent e) {
              Log.d(TAG, "由ACTION_DOWN 触发, 触摸屏幕后,尚未松开或者拖动 "+ e.getAction());
          }
      
          @Override
          public boolean onSingleTapUp(MotionEvent e) {
              Log.d(TAG, "触摸屏幕后松开,单击行为 "+ e.getAction());
              return false;
          }
      
          @Override
          public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
              Log.d(TAG, "触摸屏幕并拖动 "+ e1.getAction()+"  ,  "+e2.getAction());
              return false;
          }
      
          @Override
          public void onLongPress(MotionEvent e) {
              Log.d(TAG, "长按行为 "+ e.getAction());
          }
      
          @Override
          public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
              Log.d(TAG, "快速滑动行为 "+e1.getAction()+"  ,  "+e2.getAction());
              return false;
          }
      });

      Then take over onTouchListenerthe return:

      View.OnTouchListener touchListener = new View.OnTouchListener() {
          @Override
          public boolean onTouch(View v, MotionEvent event) {
              // ...
              gestureDetector.setIsLongpressEnabled(false);
              // return true;
              return gestureDetector.onTouchEvent(event);
          }
      };

      This allows monitoring of gesture behavior.

    • Double click callback interface: OnDoubleTapListener:

      GestureDetector.OnDoubleTapListener doubleTapListener = new GestureDetector.OnDoubleTapListener() {
          @Override
          public boolean onSingleTapConfirmed(MotionEvent e) {
              //严格单击行为。不可能是双击中的一次单击。
              return false;
          }
      
          @Override
          public boolean onDoubleTap(MotionEvent e) {
              //双击,由2次连续的单击组成。它不可能和onSingleTapConfirmed共存。
              return false;
          }
      
          @Override
          public boolean onDoubleTapEvent(MotionEvent e) {
              //表示发生了双击行为。
              // 在双击的期间,ACTION_DOWN, ACTION_MOVE 和 ACTION_UP 都会触发此回调
              return false;
              }
          };

      You can GestureDetectorinject objects with OnDoubleTapListener:

      gestureDetector.setOnDoubleTapListener(doubleTapListener);
  3. Scroller

    • Elastic sliding object, so that the sliding of View has a transition effect. If we use scrollTo/ of View scrollBy, the sliding process is completed in an instant, and the user experience is poor.
    • Instructions:

      In a custom View or ViewGroup class:

      Scroller scroller ;
      public void smoothScrollBy(int dx, int dy) {
          Log.d(TAG, "startX: " + scroller.getFinalX() + " ,startY: " + scroller.getFinalY());
          scroller.startScroll(scroller.getFinalX(), scroller.getFinalY(), dx, dy);
          invalidate();
      }
      
      @Override
      public void computeScroll() {
          if (scroller.computeScrollOffset()) {
              scrollTo(scroller.getCurrX(), scroller.getCurrY());
              postInvalidate();
          }
      }

      When you need to swipe, just call smoothScrollBy.

    • scroller.startScrollParameter description of the method:

       /**
       * Start scrolling by providing a starting point and the distance to travel.
       * The scroll will use the default value of 250 milliseconds for the
       * duration.
       * 
       * @param startX Starting horizontal scroll offset in pixels. Positive
       *        numbers will scroll the content to the left.
       * @param startY Starting vertical scroll offset in pixels. Positive numbers
       *        will scroll the content up.
       * @param dx Horizontal distance to travel. Positive numbers will scroll the
       *        content to the left.
       * @param dy Vertical distance to travel. Positive numbers will scroll the
       *        content up.
       */
      public void startScroll(int startX, int startY, int dx, int dy) {
          startScroll(startX, startY, dx, dy, DEFAULT_DURATION);
      }
      • When startX > 0, the start coordinate is offset to the left relative to the View
      • When startY > 0, the start coordinate is offset upward relative to the View
      • When dx > 0, the content of the View moves in the left direction
      • When dy > 0, the content movement direction of the View is up

3. View sliding

There are three sliding methods:
1. scrollToand scrollBy:

```
/**
 * Set the scrolled position of your view. This will cause a call to
 * {@link #onScrollChanged(int, int, int, int)} and the view will be
 * invalidated.
 * @param x the x position to scroll to
 * @param y the y position to scroll to
 */
public void scrollTo(int x, int y) {
    if (mScrollX != x || mScrollY != y) {
        int oldX = mScrollX;
        int oldY = mScrollY;
        mScrollX = x;
        mScrollY = y;
        invalidateParentCaches();
        onScrollChanged(mScrollX, mScrollY, oldX, oldY);
        if (!awakenScrollBars()) {
            postInvalidateOnAnimation();
        }
    }
}
```

Note that the content in the View is moved, and the View's position in the layout does not change.
Parameter description:
- x > 0 : the content in the View moves to the left
- y > 0 : the content in the View moves upwards It is
possible to understand the parameters and the law of movement several times.

  1. use animation

    • Animations can be defined using XML or set directly in code:

      ObjectAnimator.ofFloat(tvTest1,"translationX",0,300).setDuration(1000).start();
    • On page 132 of the "Android Development Art Exploration" book, the author mentioned that the position of the View after the moving animation has ended, and its position has not changed; although the View has moved to a new position, the View can only be clicked on the area before its movement. will respond to click events.

      However, it was found in the test that this problem has been fixed, and the android version is relatively new API 27: Android 8.1 (Oreo).

  2. Change the layout parameters:

    Directly change the coordinates and size of the View to achieve the purpose of moving the View or changing its size:

    ```
    private void moveView(View view) {
        ViewGroup.MarginLayoutParams params = (ViewGroup.MarginLayoutParams) view.getLayoutParams();
        params.leftMargin += 100;
        view.requestLayout();
        //或者重新注入布局参数:setLayoutParams
    //  view.setLayoutParams(params);
    }
    ```
    
  3. ScrollerElastic sliding: The scheme to achieve elastic sliding has been introduced in the previous section . Additionally, animations can be used ValueAnimator:

    final int deltaX = -100;
    final ValueAnimator valueAnimator = ValueAnimator.ofInt(0, 1).setDuration(1000);
    valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
        @Override
        public void onAnimationUpdate(ValueAnimator animation) {
            float fraction = animation.getAnimatedFraction();
            llTest1.scrollTo((int) (deltaX * fraction),0);
        }
    });
    //....启动动画,放在需要的地方。
    valueAnimator.start();

    In addition, there is a method: start a thread, and then send messages to the Handler continuously. In the handleMessagemethod, call scrollToor on the View scrollByto achieve the elastic sliding effect of the View. However, this is already a clever trick, excessive force and waste of unnecessary expenses.

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325611669&siteId=291194637