Open ongakuer opened 10 years ago
@ongakuer Thanks for your feedback. I ran your code (with a little modification) and I got logs like this after the Activity launched:
11-19 21:35:28.550: E/MainActivity(30584): onScrollChanged scrollY = 0
11-19 21:35:28.563: E/MainActivity(30584): onScrollChanged scrollY = 1801
Assuming that your are talking about "scrollY = 0 is incorrect"...
ObservableScrollView
is currently depends on its parent AbsListView
's onScrollListener, and to intercept into its original listener, onScrollChanged
happens at the very beginning of the view creation, and I think it's inevitable currently.
If it is a problem, could you please provide more information?
I don't know if I can solve this problem, but I'll try.
@ksoichiro Thanks for your reply. "scrollY = 0 " is correct , but "scrollY = 1801" is incorrect. When you scroll to top , scrollY's value would be negative.
That's may be a weakness of ListView. In OnScrollListener
's onScroll
method:
The first time , firstVisibleItem is 0. scrollY = 0.
The second time , firstVisibleItem is 88 (maybe) . mChildrenHeights
haven't enough values and mPrevScrolledChildrenHeight
is incorrect, so scrollY's value begin strange.
@ongakuer Thank you! I understood the issue. (But still don't know how to fix it.) Please give me some time.
@ksoichiro
http://developer.android.com/reference/android/widget/AbsListView.html#computeVerticalScrollOffset()
Use computeVerticalScrollOffset
can get scrollY simply.
mCallbacks.onScrollChanged(computeVerticalScrollOffset(), mFirstScroll, mDragging);
@ongakuer Thanks for sharing this. But is it correct offset? As written in the document above, it seems that it is the offset of the scrollbar's thumb and not the scroll position...
Yes, you can try it.
I tried and tested using ToolbarControlListViewActivity
in sample code.
At first, I enabled this debug log just before mCallbacks.onScrollChanged
in ObservableListView
,
LogUtils.v(TAG, "first: " + firstVisiblePosition + " scrollY: " + mScrollY + " first height: " + firstVisibleChild.getHeight() + " first top: " + firstVisibleChild.getTop());
and I scrolled to the bottom of the list. I got this log:
first: 90 scrollY: 13057 first height: 144 first top: -49
and then, I changed mScrollY
in the log code above to computeVerticalScrollOffset()
, I got this:
first: 90 scrollY: 9034 first height: 144 first top: -49
I tested on xxhdpi device, so the height of the each items are:
items | item height | total |
---|---|---|
0 and 1 | 168px | 168 * 2 = 336px |
2 to 89 | 144px | 144 * 88 = 12672px |
91st(position 90) item's offset is -49
, so the scrollY should be 336 + 12672 + 49 = 13057px
, in this case.
Therefore we can't use computeVerticalScrollOffset()
instead of mScrollY
...
Well,computeVerticalScrollOffset()
can not return exact offset . But the result was calculated by using mFirstPosition
and getChildAt(0)
.
We animated Toolbar by using the difference between mPrevScrollY
and mScrollY
. The relative value maybe is right whether manually scroll or scroll by setting position.
Thanks for checking this!
Then, using computeVerticalScrollOffset()
can be a workaround in your case.
But I think, replacing mScrollY
into computeVerticalScrollOffset()
in ObservableListView
has some side effects (because it's almost always incorrect offset) and it may break some standard usage: ListView that starts from position 0 and its scrollY
is used for the calculation for some other widgets animation or something.
And you can call computeVerticalScrollOffset()
with the current implementation.
So... how about approximating each item's height to getChildAt(0).getHeight()
when mChildrenHeights
doesn't know their height?
It's not a complete and correct solution, but better than now.
This solution doesn't affect to the ListViews that start from position 0.
With this solution and on my device, the first case (scrollY is 1801) became 12889, it's almost correct.
I think the scrollY may still be negative if ListView start from bottom and scroll back to top. Anyway, it's almost correct.
As you say, it may still be negative if the approximation is incorrect.
So long as the views are not drawn even once, we can not know the exactly correct scroll position, I think.
I made a fix using getChildAt(0).getHeight()
and added a sample of ListView that is scrolling from the bottom.
(Sorry but currently I have no idea of how to fix this completely.)
Thank you so much for all these discussions and investigations.
I want to scroll listview to the bottom when Activity launched, but scrollY incorrect.