Blog coding and discussion of coding about JavaScript, PHP, CGI, general web building etc.

Saturday, January 16, 2016

How to get the scroll speed on a ListView?

How to get the scroll speed on a ListView?


I have a ListView with onScrollStateChanged and onScroll event listeners. I want to be able to get the scroll speed of the ListView or some way to get the finalX location of the initiated scroll in some Event listener. Our app targets SDK version 7.

I need to measure or get the speed at which the ListView is scrolling.

Answer by QuickNick for How to get the scroll speed on a ListView?


Try it:

private class SpeedMeterOnScrollListener implements OnScrollListener {        private long timeStamp;      private int lastFirstVisibleItem;        public SpeedMeterOnScrollListener() {          timeStamp = System.currentTimeMillis();          lastFirstVisibleItem = 0;      }        @Override      public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {          long lastTime = System.currentTimeMillis();          //calculate speed by firstVisibleItem, lastFirstVisibleItem, timeStamp and lastTime          timeStamp = lastTime;          lastFirstVisibleItem = firstVisibleItem;      }        @Override      public void onScrollStateChanged(AbsListView view, int scrollState) {      }  }  

Answer by Angie for How to get the scroll speed on a ListView?


you can use android:fastScrollEnabled="true" in you and don't forget to : YourListView.requestFocusFromTouch(); after yourAdapter.notifyDataSetChanged(); because it (yourlistview) lose the focus in fast speed

Answer by Scarmysun for How to get the scroll speed on a ListView?


Division first visible items difference on time difference is not a good solution. OnScroll listener recieves onScroll event every fixed period of time, so in most cases the result of division will be "0".

So you can try something like this:

private OnScrollListener onScrollListener = new OnScrollListener() {        private int previousFirstVisibleItem = 0;      private long previousEventTime = 0;      private double speed = 0;        @Override      public void onScroll(HtcAbsListView view, int firstVisibleItem,              int visibleItemCount, int totalItemCount) {            if (previousFirstVisibleItem != firstVisibleItem){              long currTime = System.currentTimeMillis();              long timeToScrollOneElement = currTime - previousEventTime;              speed = ((double)1/timeToScrollOneElement)*1000;                previousFirstVisibleItem = firstVisibleItem;              previousEventTime = currTime;                Log.d("DBG", "Speed: " +speed + " elements/second");          }        }        @Override      public void onScrollStateChanged(HtcAbsListView view, int scrollState) {      }  };  

Answer by rharter for How to get the scroll speed on a ListView?


So this is just some theoretical pseudo-code, but wouldn't something like this work?

I think the accepted answer doesn't really work the resolution is super low (i.e. you only get a velocity after an item has been scrolled off the entire screen, but what if you have large item views?).

   int mTrackingPosition = -1;     int mLastTop;     long mLastEventTime;       @Override     public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {           // Get a new tracking position if our old one is no longer on screen         // (this also includes the first time)         if (first > mTrackingPosition || last < mTrackingPosition) {               // We get the middle position here since that's likely to stay              // on screen for a bit when scrolling up or down.             mTrackingPosition = firstVisibleItem + visibleItemCount / 2;               // Reset our times since we can't really get velocity from this             // one measurement             mLastTop = mLastEventTime = -1;               // Handle the case that this happens more than once in a             // row if that's even reasonably possible (i.e. they              // scrolled rediculously fast)         }           // Get the measurements of the tracking view         View v = view.getViewForPosition(mTrackingPosition);         int top = v.getTop();         long time = System.currentTimeMillis();           // We can only get speed if we have a last recorded time         if (mLastTop != -1 && mLastEventTime != -1) {             // Velocity = distance / time             float velocity = (mLastTop - top) / (time - mLastEventTime);               // What do you want to do with the velocity?             ...         }           // Update the last top and time so that we can track the difference         mLastTop = top;         mLastEventTime = time;     }  

Again this is just pseudo-code that I haven't tested, but I think it should work. You'll also have to reset the last time and top position values when the scroll state is STATE_IDLE.

Answer by Autobots for How to get the scroll speed on a ListView?


There is a simple way to get the speed (NOT Velocity) of the ListView, but it's not the perfect way.

/** The scroll speed threshold, it's a empiric value. */  private static final int LOW_SPEED_SCROLL_THRESHOLD = 3000;  /** The offset, in pixels, by which the content of this view is scrolled vertically. */  private long mScrollY = 0;  /** The last offset, in pixels, by which the content of this view is scrolled vertically. */  private long mLastScrollY = 0;  /** The last scroll time, in millisecond */  private long mLastTime = 0;    public void onScroll(AbsListView absListView, int firstVisibleItem, int visibleItemCount, int totalItemCount) {      final View currentItemView = absListView.getChildAt(0);      if (currentItemView != null) {          // The first try to scroll, reset the last time flag          if (mLastTime == 0) {              mLastTime = System.currentTimeMillis();              return;          }              final int height = currentItemView.getHeight();          final int currentPos = firstVisibleItem;          final int currentPosOffset = currentItemView.getTop(); // < 0          mScrollY = currentPos * height - currentPosOffset;          final long deltaOffset = mScrollY - mLastScrollY;          final long currTime = System.currentTimeMillis();          if (currTime == mLastTime) {              return;          }            final long speed = deltaOffset * 1000 / (currTime - mLastTime);          if (Math.abs(speed) < LOW_SPEED_SCROLL_THRESHOLD) {              // low speed          } else {              // high speed          }            mLastTime = currTime;          mLastScrollY = mScrollY;      } else {          resetScrollState();      }  }    private void resetScrollState() {      mLastTime = 0;      mScrollY = 0;      mLastScrollY = 0;  }  
  1. The perfect way is to use current scroll Velocity when callback onScroll?in AbsListView, we can get the velocity with FlingRunnable#mScroller.getCurrVelocity(), but unfortunately?the AbsListView doesn't provide the public method of getCurrVelocity()? so if we want to get this method, there are two methods to get it
    • Reflect this method, but I think it has the performance problem when get it onScroll callback
    • Copy the AbsListView.java source and create a new class of AbsListViewEx, provide a public method of getCurrVelocity() in this class, let new ListViewEx extends from AbsListViewEx, but it also has some problem: 1) it maybe a complex thing 2) the ListViewEx may has compatibility problem. However, this way I think is better than Reflect method.


Fatal error: Call to a member function getElementsByTagName() on a non-object in D:\XAMPP INSTALLASTION\xampp\htdocs\endunpratama9i\www-stackoverflow-info-proses.php on line 72

0 comments:

Post a Comment

Popular Posts

Powered by Blogger.