Is there any way similar like using smoothScrollToPosition with control over speed or the time it takes to scroll smoothly?
Now i am using below snippet to scrool to pos
int firstVisible = lv.getFirstVisiblePosition();
int lastVisible = lv.getLastVisiblePosition();
if (firstVisible > pos)
lv.smoothScrollToPosition(pos, pos - firstVisible - 2);
if (pos > lastVisible)
lv.smoothScrollToPosition(pos, pos + lastVisible + 3);
From this i modified to aabove snippet as below
int childheight = lv.getChildAt(firstVisible).getHeight();
if (firstVisible > pos)
lv.smoothScrollBy(childheight*pos, 800);
if (pos > lastVisible)
lv.smoothScrollBy(childheight*pos, 1200);
But, i get nullpointer exceptions at
int childheight = lv.getChildAt(firstVisible).getHeight();
Edit
i am in need of scrooling automatically to a childView by a button press by user,say MENU button. I am not facing the problem of list scrolling slowly because of doing resource intensive task to populate listview. All i want is the functionality of smoothScrollToPosition with smoothscrooltoPosition with velocity control
Related
I have a RecyclerView + LinearLayoutManger which is using an adapter that holds chat messages. I limit the number of chat messages to the most 100 recent. This issue is that when I remove the older chats, the scroll position of the chats in the recyclerview changes because index 0 was removed. I began writing the code below:
int firstVisiblePosition = layoutManager.findFirstVisibleItemPosition();
View v = layoutManager.getChildAt(firstVisiblePosition);
if (firstVisiblePosition > 0 && v != null) {
int offsetTop = //need to get the view offset here;
chatAdapter.notifyDataSetChanged();
if (firstVisiblePosition - 1 >= 0 && chatAdapter.getItemCount() > 0) {
layoutManager.scrollToPositionWithOffset(firstVisiblePosition - 1, offsetTop);
}
}
I thought it would be easy to get the visible offset of the first visible item position. Ex. if the first visible view is 300dp but only the last 200dp is visible, I would like to get the 100 offset.
This way I could use scrollToPositionWithOffset(firstVisiblePosition - 1, offsetTop).
Am I missing something here? This seems like it would be an easy problem to figure out, but I haven't seen any methods that would support this.
#Blackbelt. Thank you for getting me on the right track.
The offset that I needed was actually just v.getTop();
My real problem was in getChildAt(). Apparently getChildAt begins at the first visible position, not at the position of the adapter. The documentation is poorly written in this case.
Here is the resulting code.
int firstVisiblePosition = layoutManager.findFirstVisibleItemPosition();
View v = layoutManager.getChildAt(0);
if (firstVisiblePosition > 0 && v != null) {
int offsetTop = v.getTop();
chatAdapter.notifyDataSetChanged();
if (firstVisiblePosition - 1 >= 0 && chatAdapter.getItemCount() > 0) {
layoutManager.scrollToPositionWithOffset(firstVisiblePosition - 1, offsetTop);
}
}
I have a list view of 300 mp3 songs and suppose song 52 is playing. So I want next time when user opens the list of song, the list row in front of him must starts from row 52 (while up and down are still rows). I tried using
public View getViewByPosition(int pos, ListView listView) {
final int firstListItemPosition = listView.getFirstVisiblePosition();
final int lastListItemPosition = firstListItemPosition + listView.getChildCount() - 1;
if (pos < firstListItemPosition || pos > lastListItemPosition ) {
return listView.getAdapter().getView(pos, null, listView);
} else {
final int childIndex = pos - firstListItemPosition;
return listView.getChildAt(childIndex);
}
}
and also
adapter.getItem(52);
But both are pointless methods and dont take me to row 52. (These methods are what I used, but might not be the solution) Also I got no solution googling it. Please let me know if you guys can deal with this !!
A big thanks to you for listening!
This line will select n row starting from top:
listview.setSelectionFromTop(n, 0);
So for your case as you want to select 52 row you have to right following code on start of activity after setting your adapter
listview.setSelectionFromTop(52, 0);
try this:
link
listview.smoothScrollToPosition(yourPosition);
I wanna when listview 1 is scrolled by user, listview 2 also is scroll like listview 1 (exactly in pixel).
I tried to scroll listview 2 by smoothScrollByOffset(offset), but it scrolls more than listview 1.
I dont know why?
What happened with smoothScrollByOffset(offset) or I miss something?
Further information:
Code to scroll listview 2 (in onScroll callback of listview 1):
int previsous = 0;
public void onScroll(AbsListView view, int firstVisibleItem,
int visibleItemCount, int totalItemCount) {
//get current position in pixel of listview 1
View c = lv1.getChildAt(0);
int scrolly = -c.getTop() + lv1.getFirstVisiblePosition() * c.getHeight();
//Difference in pixel with the last scroll
int delta = scrolly - previsous;
Log.d("scroll", "listview 1 has scrolled: " +
scrolly + "| Difference with the last " + delta);
//scroll listview 2 by delta
lv2.smoothScrollByOffset(delta);
previsous = scrolly;
}
Screen shot for diagnostic:
Try to use smoothScrollToPosition (int position) instead of smoothScrollByOffset (int offset), I hope this will help you, Let me know what happened.
You are using the wrong method. The smoothScrollByOffset() doesn't accept pixels, but number of positions. Use smoothScrollBy(int distance, int duration)
I am trying to build my own grid view functions - extending on the GridView.
The only thing I cannot solve is how to get the current scroll position of the GridView.
getScrollY() does always return 0, and the onScrollListener's parameters are just a range of visible child views, not the actual scroll position.
This does not seem very difficult, but I just can't find a solution in the web.
Anybody here who have an idea?
I did not find any good solution,
but this one is at least able to maintain the scroll position kind of pixel-perfectly:
int offset = (int)(<your vertical spacing in dp> * getResources().getDisplayMetrics().density);
int index = mGrid.getFirstVisiblePosition();
final View first = container.getChildAt(0);
if (null != first) {
offset -= first.getTop();
}
// Destroy the position through rotation or whatever here!
mGrid.setSelection(index);
mGrid.scrollBy(0, offset);
By that you can not get an absolute scroll position, but a visible item + displacement pair.
NOTES:
This is meant for API 8+.
You can get with mGrid.getVerticalSpacing() in API 16+.
You can use mGrid.smoothScrollToPositionFromTop(index, offset) in API 11+ instead of the last two lines.
Hope that helps and gives you an idea.
On Gingerbread, GridView getScrollY() works in some situations, and in some doesn't. Here is an alternative based on the first answer. The row height and the number of columns have to be known (and all rows must have equal height):
public int getGridScrollY()
{
int pos, itemY = 0;
View view;
pos = getFirstVisiblePosition();
view = getChildAt(0);
if(view != null)
itemY = view.getTop();
return YFromPos(pos) - itemY;
}
private int YFromPos(int pos)
{
int row = pos / m_numColumns;
if(pos - row * m_numColumns > 0)
++row;
return row * m_rowHeight;
}
The first answer also gives a good clue on how to pixel-scroll a GridView. Here is a generalized solution, which will scroll a GridView equivalent to scrollTo(0, scrollY):
public void scrollGridToY(int scrollY)
{
int row, off, oldOff, oldY, item;
// calc old offset:
oldY = getScrollY(); // getGridScrollY() will not work here
row = oldY / m_rowHeight;
oldOff = oldY - row * m_rowHeight;
// calc new offset and item:
row = scrollY / m_rowHeight;
off = scrollY - row * m_rowHeight;
item = row * m_numColumns;
setSelection(item);
scrollBy(0, off - oldOff);
}
The functions are implemented inside a subclassed GridView, but they can be easily recoded as external.
I am trying to build my own grid view functions - extending on the GridView.
The only thing I cannot solve is how to get the current scroll position of the GridView.
getScrollY() does always return 0, and the onScrollListener's parameters are just a range of visible child views, not the actual scroll position.
This does not seem very difficult, but I just can't find a solution in the web.
Anybody here who have an idea?
I did not find any good solution,
but this one is at least able to maintain the scroll position kind of pixel-perfectly:
int offset = (int)(<your vertical spacing in dp> * getResources().getDisplayMetrics().density);
int index = mGrid.getFirstVisiblePosition();
final View first = container.getChildAt(0);
if (null != first) {
offset -= first.getTop();
}
// Destroy the position through rotation or whatever here!
mGrid.setSelection(index);
mGrid.scrollBy(0, offset);
By that you can not get an absolute scroll position, but a visible item + displacement pair.
NOTES:
This is meant for API 8+.
You can get with mGrid.getVerticalSpacing() in API 16+.
You can use mGrid.smoothScrollToPositionFromTop(index, offset) in API 11+ instead of the last two lines.
Hope that helps and gives you an idea.
On Gingerbread, GridView getScrollY() works in some situations, and in some doesn't. Here is an alternative based on the first answer. The row height and the number of columns have to be known (and all rows must have equal height):
public int getGridScrollY()
{
int pos, itemY = 0;
View view;
pos = getFirstVisiblePosition();
view = getChildAt(0);
if(view != null)
itemY = view.getTop();
return YFromPos(pos) - itemY;
}
private int YFromPos(int pos)
{
int row = pos / m_numColumns;
if(pos - row * m_numColumns > 0)
++row;
return row * m_rowHeight;
}
The first answer also gives a good clue on how to pixel-scroll a GridView. Here is a generalized solution, which will scroll a GridView equivalent to scrollTo(0, scrollY):
public void scrollGridToY(int scrollY)
{
int row, off, oldOff, oldY, item;
// calc old offset:
oldY = getScrollY(); // getGridScrollY() will not work here
row = oldY / m_rowHeight;
oldOff = oldY - row * m_rowHeight;
// calc new offset and item:
row = scrollY / m_rowHeight;
off = scrollY - row * m_rowHeight;
item = row * m_numColumns;
setSelection(item);
scrollBy(0, off - oldOff);
}
The functions are implemented inside a subclassed GridView, but they can be easily recoded as external.