Android custom control imitates ios pull down rebound effect

  • 2021-10-27 09:21:15
  • OfStack

There are many similar articles on the Internet, most of which are realized by inheriting listview (mainly listview. addHeaderView () and listview. addFooterView add view at the beginning and end of listview, or use the above two listview self-contained functions to realize the drop-down refresh function, which is not prepared to be introduced here. Interested friends can try it themselves).

In this paper, we mainly give the linear layout (relative layout, frame layout) of android a pull-down or pull-up rebound effect. We can often see in ios, Even if there is only one control in one page, This 1 control only accounts for less than 1/10 of the whole page, But when we pull down the whole page, there will still be a rebound effect (here we don't consider whether such a page is beautiful, just analyze how to realize it). Obviously, in android, we will not use listview in order to realize this page with only one item (and it won't get more), but we will directly use linear layout or relatively simple viewgroup. So here I also add pull-down or pull-up rebound effect for linear layout.

Implementation process:

1. Create a new class to inherit LinearLayout

2. Instantiate Scroller (for sliding) and GestureDetector in the construction method (there are many implementation methods on the Internet that replicate onTouchEvent method and write onTouchEvent method very long. I don't like this way very much. I also recommend you to use gestures, which is very easy to use);

3. Overwrite computeScroll (), onTouchEvent (MotionEvent event) (in this case, leave the touch screen to GestureDetector)
4. Actual scrolling in computeScroll ()

Before starting the concrete implementation, we must first introduce several important functions to be used


mScroller.getCurrX() // Get mScroller Position of current horizontal scroll 
mScroller.getCurrY() // Get mScroller Current position of vertical scrolling 
mScroller.getFinalX() // Get mScroller Horizontal position of final stop 
mScroller.getFinalY() // Get mScroller Vertical position of final stop 
mScroller.setFinalX(int newX) // Settings mScroller The final stay in the horizontal position, without animation effect, jumps directly to the target position 
mScroller.setFinalY(int newY) // Settings mScroller Eventually stay in the vertical position, without animation effect, and jump directly to the target position 
 
// Scroll, startX, startY Is the position to start scrolling, dx,dy Is the offset of scrolling , duration Is the time to complete the scroll 
mScroller.startScroll(int startX, int startY, int dx, int dy) // Use the default completion time 250ms
mScroller.startScroll(int startX, int startY, int dx, int dy, int duration)
 
mScroller.computeScrollOffset() // The return value is boolean , true Indicates that scrolling has not been completed, false Indicates that scrolling is complete. This is 1 A very important method, usually put in View.computeScroll() Used to determine whether scrolling is over. 

The above methods of Scroller can help us realize sliding.

Next, we will introduce the implementation of GestureDetector. OnGestureListener

Because we did not give MotionEvent.ACTION_UP to GestureDetector in onTouchEvent, some methods in GestureDetector. OnGestureListener will not respond, and the return value of down event should be set to true in GestureDetector. OnGestureListener, otherwise the onscroll method will not respond

The next step is the concrete implementation:


public class SqqLinearLayout extends LinearLayout { 
 private Scroller mScroller; 
 private GestureDetector mGestureDetector; 
  
 public SqqLinearLayout (Context context) { 
  this(context, null); 
 } 
  
 public SqqLinearLayout (Context context, AttributeSet attrs) { 
  super(context, attrs); 
  mScroller = new Scroller(context); 
  mGestureDetector = new GestureDetector(context, new GestureListenerImpl()); 
 } 
 
  //startScroll If there is no real movement after that, this function will be automatically called to realize the movement 
 @Override 
 public void computeScroll() { 
  if (mScroller.computeScrollOffset()) { 
 
   scrollTo(mScroller.getCurrX(), mScroller.getCurrY()); 
   // Must be executed postInvalidate() Thereby calling computeScroll()
   // Actually , Call here invalidate(); May also 
   postInvalidate(); 
  } 
  super.computeScroll(); 
 } 
  
 @Override 
 public boolean onTouchEvent(MotionEvent event) { 
  switch (event.getAction()) { 
  case MotionEvent.ACTION_UP : 
  // Return to the original position when the finger is lifted 
   prepareScroll(0, 0); 
   break; 
  default: 
   // The rest is handed over to GestureDetector Gesture processing 
   return mGestureDetector.onTouchEvent(event); 
  } 
  return super.onTouchEvent(event); 
 } 
 
 
 class GestureListenerImpl implements GestureDetector.OnGestureListener {
 @Override
 public boolean onDown(MotionEvent e) {
  return true;
 }
 
 @Override
 public void onShowPress(MotionEvent e) {
 
 }
 
 @Override
 public boolean onSingleTapUp(MotionEvent e) {
  return false;
 }
 
 @Override
 public boolean onScroll(MotionEvent e1, MotionEvent e2,float distanceX, float distanceY) {
  int disY = (int) ((distanceY - 0.5)*0.65);
  beginScroll(0, disY);
  return false;
 }
 
 public void onLongPress(MotionEvent e) {
 
 }
 
 @Override
 public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,float velocityY) {
  return false;
 }
 
 } 
 
 
 // Scroll to Target Location  
 protected void prepareScroll(int fx, int fy) { 
  int dx = fx - mScroller.getFinalX(); 
  int dy = fy - mScroller.getFinalY(); 
  beginScroll(dx, dy,1000); // After testing 1s It's good  
 } 
 
 
  // Set the relative offset of scrolling  
 protected void beginScroll(int dx, int dy) { 
  mScroller.startScroll(mScroller.getFinalX(), mScroller.getFinalY(), dx, dy); 
  
  // Must be executed invalidate() Thereby calling computeScroll()
  //invalidate();
 // Above 1 It seems that the comment of the sentence has no effect, and it has not been found yet 
 } 
 
  // Set the relative offset of scrolling  
 protected void beginScroll(int dx, int dy,int duration) { 
  mScroller.startScroll(mScroller.getFinalX(), mScroller.getFinalY(), dx, dy,duration); 
  
  // Must be executed invalidate() Thereby calling computeScroll()
  //invalidate();
 // Above 1 It seems that the comment of the sentence has no effect, and it has not been found yet 
 } 
 
 
}

The pull-down rebound effect of linear layout is realized above, and the realization of relative layout is the same as that of above, but it inherits RelativeLayout. Therefore, with the principle of not writing repeated code, I will make an optimization in the next article, and write the drop-down refresh of linear layout and relative layout into a class, with specific linear layout and relative layout as parameters or other forms. Of course, this is just an idea, and I don't know if it can be well realized.

Project download address: Android custom control imitates ios pull-down rebound effect


Related articles: