SoFunction
Updated on 2025-04-09

Android custom viewgroup scrollable layout GestureDetector gesture listening (5)

This article has the effect and the previous article:https:///article/The effect is the same, but no longer write code in OnTouchEvent, but use the system's own class GestureDetector to listen for gestures and sliding events, etc. It has built-in events such as sliding, clicking, long pressing, etc., and it has fast sliding, which is more convenient and is better than the details you write by yourself.

Code:

package ;

import ;
import ;
import ;
import ;
import ;
import ;
import ;
import ;
import ;

/**
  * Custom ViewGroup (Landscape Scroll)
  */
public class ScrollViewGroup extends ViewGroup {
 //Scrolling calculation auxiliary class private Scroller mScroller;
 //Screen Width private int screenWidth;
 //The maximum distance that can be moved private int mMaxDistance;
 //Custom gesture listening class private ScrollTouchLisener mTouchLisener;
 //Gesturing Monitor private GestureDetector mDetector;

 /**
   * Called when creating an object using the new keyword
   */
 public ScrollViewGroup(Context context) {
  this(context, null);
 }

 /**
   * Called when used in XML files
   */
 public ScrollViewGroup(Context context, AttributeSet attrs) {
  this(context, attrs, 0);
 }

 /**
   * Called in the xml file and when custom properties are used
   */
 public ScrollViewGroup(Context context, AttributeSet attrs, int defStyleAttr) {
  super(context, attrs, defStyleAttr);
  init(context);
 }

 /**
   * Initialization method
   * Initialize the scrolling auxiliary class Scroller and calculate the screen width
   */
 private void init(Context context) {
  //Initialize the auxiliary class  mScroller = new Scroller(context);
  //Get screen width  WindowManager manager = (WindowManager) context
    .getSystemService(Context.WINDOW_SERVICE);
  DisplayMetrics outMetrics = new DisplayMetrics();
  ().getMetrics(outMetrics);
  screenWidth = ;
  //Gesturing indicator initialization  mTouchLisener = new ScrollTouchLisener();
  mDetector = new GestureDetector(context, mTouchLisener);
 }

 /**
   * Method that needs to be rewrited when scrolling, used to control scrolling
   */
 @Override
 public void computeScroll() {
  //Judge the stop when scrolling  if (()) {
   //Scroll to the specified position   scrollTo((), ());
   //This sentence must be written, otherwise it cannot be refreshed in real time   postInvalidate();
  }
 }

 /**
   * Finger touch screen event monitoring
   */
 @Override
 public boolean onTouchEvent(MotionEvent event) {
  (event);
  if (() == MotionEvent.ACTION_UP) {
   (event);
  }
  return true;
 }

 /*
   *Measurement method, measure the width and height of the parent layout
   */
 @Override
 protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
  //Reset width and height  (measureWidth(widthMeasureSpec, heightMeasureSpec), measureHeight(widthMeasureSpec, heightMeasureSpec));
 }

 /**
   * Measure width
   */
 private int measureWidth(int widthMeasureSpec, int heightMeasureSpec) {
  // Width  int sizeWidth = (widthMeasureSpec);
  int modeWidth = (widthMeasureSpec);
  //Width of parent control (wrap_content)  int width = 0;
  int childCount = getChildCount();

  //Remeasure the width of the subview and the maximum height  for (int i = 0; i < childCount; i++) {
   View child = getChildAt(i);
   measureChild(child, widthMeasureSpec, heightMeasureSpec);
   MarginLayoutParams lp = (MarginLayoutParams) ();
   int childWidth = () +  + ;
   width += childWidth;
  }
  return modeWidth ==  ? sizeWidth : width;
 }

 /**
   * Measure the height
   */
 private int measureHeight(int widthMeasureSpec, int heightMeasureSpec) {
  //high  int sizeHeight = (heightMeasureSpec);
  int modeHeight = (heightMeasureSpec);
  //The parent control's high (wrap_content)  int height = 0;
  int childCount = getChildCount();

  //Remeasure the width of the subview and the maximum height  for (int i = 0; i < childCount; i++) {
   View child = getChildAt(i);
   measureChild(child, widthMeasureSpec, heightMeasureSpec);
   MarginLayoutParams lp = (MarginLayoutParams) ();
   int childHeight = () +  + ;
   height += childHeight;
  }
  height = height / childCount;
  return modeHeight ==  ? sizeHeight : height;
 }

 /**
   * Set position for sub-layout
   */
 @Override
 protected void onLayout(boolean changed, int l, int t, int r, int b) {
  int childLeft = 0;//The spacing on the left side of the subview  int childWidth;//The width of the subview  int height = getHeight();//The width of the screen  int childCount = getChildCount();//The number of subviews  for (int i = 0; i < childCount; i++) {
   View child = getChildAt(i);
   MarginLayoutParams lp = (MarginLayoutParams) ();
   childWidth = () +  + ;
   (childLeft, 0, childLeft + childWidth, height);
   childLeft += childWidth;
  }
 }

 @Override
 public LayoutParams generateLayoutParams(AttributeSet attrs) {
  return new MarginLayoutParams(getContext(), attrs);
 }

 /*
   *Press event ACTION_DOWN
   */
 public boolean onDown(MotionEvent e) {
  //If scrolling is stopped, cancel the animation (that is, stop scrolling when finger presses)  if (!()) {
   ();
  }
  return false;
 }
 /*
  *Release event ACTION_UP
  */
 public boolean onUp(MotionEvent e) {
  //Get the last child View  View lastChild = getChildAt(getChildCount() - 1);
  //Get the maximum sliding distance of the slide (the coordinates of the right border of the last Child minus the width of the screen)  int finalyChild = (int) (() + () - screenWidth);
  mMaxDistance = finalyChild;
  //If the sliding distance is less than the leftmost (0) of the first control, it will rebound to point (0,0)  if (getScrollX() < 0) {
   scrollTo(0, 0);
  }
  //If the sliding distance is greater than the maximum sliding distance, slide to the last subView  if (getScrollX() >= finalyChild)
   scrollTo(finalyChild, 0);
  //Refresh the interface  invalidate();
  return false;
 }

 /*
   *ACTION_DOWN, short press does not move
   */
 public void onShowPress(MotionEvent e) {
 }

 /*
   *Short press ACTION_DOWN, ACTION_UP
   */
 public boolean onSingleTapUp(MotionEvent e) {
  return false;
 }

 /*
   *ACTION_DOWN, slow swipe
   */
 public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
  //scroll  scrollBy((int) distanceX, 0);
  return false;
 }

 // ACTION_DOWN, long press and do not slide public void onLongPress(MotionEvent e) {
 }

 /*
   *ACTION_DOWN, fast slide, ACTION_UP
   */
 public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
  (getScrollX(), 0, (int) -velocityX, 0, 0, mMaxDistance, 0, 0);
  return false;
 }

 /**
   * Custom gesture listening class
   */
 private class ScrollTouchLisener implements  {

  //Press event  @Override
  public boolean onDown(MotionEvent e) {
   return (e);
  }

  //Click event  @Override
  public void onShowPress(MotionEvent e) {
   (e);
  }

  //Finger lift event  @Override
  public boolean onSingleTapUp(MotionEvent e) {
   return (e);
  }

  //Scrolling event  @Override
  public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
   return (e1, e2, distanceX, distanceY);
  }

  //Long press event  @Override
  public void onLongPress(MotionEvent e) {
   (e);
  }

  //Sliding Event  @Override
  public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
   return (e1, e2, velocityX, velocityY);
  }
 }

}

The above is all the content of this article. I hope it will be helpful to everyone's study and I hope everyone will support me more.