Android: How to detect when a scroll has ended

后端 未结 14 799
误落风尘
误落风尘 2020-11-27 10:54

I am using the onScroll method of GestureDetector.SimpleOnGestureListener to scroll a large bitmap on a canvas. When the scroll has ended I want to redraw the bitmap in case

相关标签:
14条回答
  • 2020-11-27 11:42

    i have not tried / used this but an idea for an approach:

    stop / interrupt redrawing canvas on EVERY scroll event wait 1s and then start redrawing canvas on EVERY scroll.

    this will lead to performing the redraw only at scroll end as only the last scroll will actually be uninterrupted for the redraw to complete.

    hope this idea helps you :)

    0 讨论(0)
  • 2020-11-27 11:47

    I was looking into this same issue. I saw Akos Cz answer to your question. I created something similar, but with my version I noticed that it only worked for a regular scroll - meaning one that doesn't generate a fling. But if a fling did get generated - regardless if I processed a fling or not, then it did NOT detect the "ACTION_UP" in "onTouchEvent". Now maybe this was just something with my implementation, but if it was I couldn't figure out why.

    After further investigation, I noticed that during a fling, the "ACTION_UP" was passed into "onFling" in "e2" every time. So I figured that must be why it wasn't being handled in "onTouchEvent" in those instances.

    To make it work for me I only had to call a method to handle the "ACTION_UP" in "onFling" and then it worked for both types of scrolling. Below are the exact steps I took to implement in my app:

    -initialized a "gestureScrolling" boolean to "false" in a constructor.

    -I set it to "true" in "onScroll"

    -created a method to handle the "ACTION_UP" event. Inside that event, I reset "gestureSCrolling" to false and then did the rest of the processing I needed to do.

    -in "onTouchEvent", if an "ACTION_UP" was detected and "gestureScrolling" = true, then I called my method to handle "ACTION_UP"

    -And the part that I did that was different was: I also called my method to handle "ACTION_UP" inside of "onFling".

    0 讨论(0)
  • 2020-11-27 11:50
    SimpleOnGestureListener.onFling() 
    

    It seems to take place when a scroll ends (i.e. the user lets the finger go), that's what I am using and it works great for me.

    0 讨论(0)
  • 2020-11-27 11:51

    Coming back to this after a few months I've now followed a different tack: using a Handler (as in the Android Snake sample) to send a message to the app every 125 milliseconds which prompts it to check whether a Scroll has been started and whether more than 100 milliseconds has elapsed since the last scroll event.

    This seems to work pretty well, but if anyone can see any drawbacks or possible improvements I should be grateful to hear of them.

    The relevant the code is in the MyView class:

    public class MyView extends android.view.View {
    
    ...
    
    private long timeCheckInterval = 125; // milliseconds
    private long scrollEndInterval = 100;
    public long latestScrollEventTime;
    public boolean scrollInProgress = false;
    
    public MyView(Context context) {
        super(context);
    }
    
    private timeCheckHandler mTimeCheckHandler = new timeCheckHandler();
    
    class timeCheckHandler extends Handler{
    
            @Override
            public void handleMessage(Message msg) {
            long now = System.currentTimeMillis();
            if (scrollInProgress && (now>latestScrollEventTime+scrollEndInterval)) {
                        scrollInProgress = false;
    

    // Scroll has ended, so insert code here

    // which calls doDrawing() method

    // to redraw bitmap re-centred where scroll ended

                        [ layout or view ].invalidate();
            }
            this.sleep(timeCheckInterval);
            }
    
            public void sleep(long delayMillis) {
                this.removeMessages(0);
                sendMessageDelayed(obtainMessage(0), delayMillis);
                }
        }
    }
    
    @Override protected void onDraw(Canvas canvas){
            super.onDraw(canvas);
    

    // code to draw large buffer bitmap onto the view's canvas // positioned to take account of any scroll that is in progress

    }
    
    public void doDrawing() {
    

    // code to do detailed (and time-consuming) drawing // onto large buffer bitmap

    // the following instruction resets the Time Check clock // the clock is first started when // the main activity calls this method when the app starts

            mTimeCheckHandler.sleep(timeCheckInterval);
    }
    

    // rest of MyView class

    }

    and in the MyGestureDetector class

    public class MyGestureDetector extends SimpleOnGestureListener {
    
    @Override
    public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX,
            float distanceY) {
    
        [MyView].scrollInProgress = true;
            long now = System.currentTimeMillis();  
        [MyView].latestScrollEventTime =now;
    
        [MyView].scrollX += (int) distanceX;
        [MyView].scrollY += (int) distanceY;
    

    // the next instruction causes the View's onDraw method to be called // which plots the buffer bitmap onto the screen // shifted to take account of the scroll

        [MyView].invalidate();
    
    }
    

    // rest of MyGestureDetector class

    }

    0 讨论(0)
  • 2020-11-27 11:52

    I think this will work as you need

    protected class SnappingGestureDetectorListener extends SimpleOnGestureListener{
    
        @Override
        public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY){
            boolean result = super.onScroll(e1, e2, distanceX, distanceY);
    
            if(!result){
                //Do what you need to do when the scrolling stop here
            }
    
            return result;
        }
    
    }
    
    0 讨论(0)
  • 2020-11-27 11:53

    You should take a look at http://developer.android.com/reference/android/widget/Scroller.html. Especially this could be of help (sorted by relevance):

    isFinished();
    computeScrollOffset();
    getFinalY(); getFinalX(); and getCurrY() getCurrX()
    getDuration()
    

    This implies that you have to create a Scroller.

    If you want to use touching you could also use GestureDetector and define your own canvas scrolling. The following sample is creating a ScrollableImageView and in order to use it you have to define the measurements of your image. You can define your own scrolling range and after finishing your scrolling the image gets redrawn.

    http://www.anddev.org/viewtopic.php?p=31487#31487

    Depending on your code you should consider invalidate(int l, int t, int r, int b); for the invalidation.

    0 讨论(0)
提交回复
热议问题