Android:StaggeredGridLayoutManager 在初始化时滚动到顶部
Android: StaggeredGridLayoutManager scroll to top while initializing
我正在为我的图片库使用 StaggeredGridLayoutManager。我设置了 setReverseLayout(true)
,以便图像从底部堆叠。
我面临的问题是,在应用程序初始化时,滚动条指向图库底部。当用户首次启动应用程序时,我希望滚动条位于图库的顶部。
我试过使用 scrollToPosition
(以下代码片段),但滚动最终出现在画廊中间的某个地方,可能是因为在调用 [= 时图像没有正确加载13=].
mLayoutManager = new StaggeredGridLayoutManager(2,StaggeredGridLayoutManager.VERTICAL);
mLayoutManager.setReverseLayout(true);
mRecyclerView.setLayoutManager(mLayoutManager);
mImageList = ((MainActivity)getActivity()).getImages();
adapter = new ImageAdapter(getActivity(),mImageList);
mRecyclerView.setAdapter(adapter);
mRecyclerView.scrollToPosition(mImageList.size()-1);
是否有正确的方法将滚动条指向顶部,而不是底部?
尝试通过调用找到第一个可见位置
findFirstCompletelyVisibleItemPositions
或findFirstVisibleItemPositions
使用从先前方法获得的位置调用您的回收器视图 scrollToPosition
尝试使用 StaggeredGridLayoutManager
的 scrollToPositionWithOffset()
功能。我发现它比 scrollToPosition
更可靠。还要确保在 Handler().post()
内执行此函数。这将导致 Runnable
被添加到消息队列中。一旦 UI 线程空闲,它将 运行。
new Handler().post(new Runnable() {
@Override
public void run() {
staggeredGridLayoutManager.scrollToPositionWithOffset(mImageList.size() - 1, 0);
}
});
我在 dataobserver 中使用了 scrolltoposition,现在它工作正常..
当 recyclerview 加载时,使用以下代码可以看到顶部的项目:
rcAdapter.registerAdapterDataObserver(new RecyclerView.AdapterDataObserver() {
@Override
public void onItemRangeInserted(int positionStart, int itemCount) {
super.onItemRangeInserted(positionStart, itemCount);
int count = rcAdapter.getItemCount();
mRecyclerView.scrollToPosition(itemCount-1);
}
});
要像在聊天视图中一样滚动到底部以查看新添加的项目,请使用以下代码。
rcAdapter.registerAdapterDataObserver(new RecyclerView.AdapterDataObserver() {
@Override
public void onItemRangeInserted(int positionStart, int itemCount) {
super.onItemRangeInserted(positionStart, itemCount);
int count = rcAdapter.getItemCount();
int lastVisiblePositions[] = new int[2]; //for 2 columns
int lastVisiblePosition = staggeredGridLayoutManager.findLastCompletelyVisibleItemPositions(lastVisiblePositions)[0];
// If the recycler view is initially being loaded or the user is at the bottom of the list, scroll
// to the bottom of the list to show the newly added message.
if (lastVisiblePosition == -1 ||
(positionStart >= (count- 1) && lastVisiblePosition == (positionStart - 1))) {
mRecyclerView.scrollToPosition(positionStart);
}
}
});
我之前解决过类似的问题,这里是方法:
mRecyclerView.getViewTreeObserver().addOnGlobalLayoutListener(
new ViewTreeObserver.OnGlobalLayoutListener() {
@SuppressWarnings("deprecation")
@Override
public void onGlobalLayout() {
ViewTreeObserver observer = mRecyclerView.getViewTreeObserver();
scrollRecyclerViewToTop();
if (!observer.isAlive()) {
return;
}
if (mScrolledByUser) {
if (hasJellyBeanApi()) {
observer.removeOnGlobalLayoutListener(this);
} else {
observer.removeGlobalOnLayoutListener(this);
}
}
}
});
并且:
mRecyclerView.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
mScrollByUser = true;
return false;
}
});
并且:
private void scrollRecyclerViewToTop() {
mRecyclerView.scrollToPosition(0);
mRecyclerView.scrollBy(0, Integer.MIN_VALUE);
}
意思很简单:让RecyclerView
一直滚动到顶部直到用户触摸它。希望对您有所帮助。
这段代码可能对你有帮助,我也在代码
中使用了这个link
https://guides.codepath.com/android/Endless-Scrolling-with-AdapterViews-and-RecyclerView
Every AdapterView (such as ListView and GridView) has support for
binding to the OnScrollListener events which are triggered whenever a
The user scrolls through the collection. Using this system, we can define
a basic EndlessScrollListener which supports most use cases by
creating our own class that extends OnScrollListener:
public abstract class EndlessScrollListener implements AbsListView.OnScrollListener {
// The minimum number of items to have below your current scroll position
// before loading more.
private int visibleThreshold = 5;
// The current offset index of data you have loaded
private int currentPage = 0;
// The total number of items in the dataset after the last load
private int previousTotalItemCount = 0;
// True if we are still waiting for the last set of data to load.
private boolean loading = true;
// Sets the starting page index
private int startingPageIndex = 0;
public EndlessScrollListener() {
}
public EndlessScrollListener(int visibleThreshold) {
this.visibleThreshold = visibleThreshold;
}
public EndlessScrollListener(int visibleThreshold, int startPage) {
this.visibleThreshold = visibleThreshold;
this.startingPageIndex = startPage;
this.currentPage = startPage;
}
// This happens many times a second during a scroll, so be wary of the code you place here.
// We are given a few useful parameters to help us work out if we need to load some more data,
// but first we check if we are waiting for the previous load to finish.
@Override
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount)
{
// If the total item count is zero and the previous isn't, assume the
// list is invalidated and should be reset back to initial state
if (totalItemCount < previousTotalItemCount) {
this.currentPage = this.startingPageIndex;
this.previousTotalItemCount = totalItemCount;
if (totalItemCount == 0) { this.loading = true; }
}
// If it's still loading, we check to see if the dataset count has
// changed, if so we conclude it has finished loading and update the current page
// number and total item count.
if (loading && (totalItemCount > previousTotalItemCount)) {
loading = false;
previousTotalItemCount = totalItemCount;
currentPage++;
}
// If it isn't currently loading, we check to see if we have breached
// the visibleThreshold and need to reload more data.
// If we do need to reload some more data, we execute onLoadMore to fetch the data.
if (!loading && (firstVisibleItem + visibleItemCount + visibleThreshold) >= totalItemCount ) {
loading = onLoadMore(currentPage + 1, totalItemCount);
}
}
// Defines the process for actually loading more data based on page
// Returns true if more data is being loaded; returns false if there is no more data to load.
public abstract boolean onLoadMore(int page, int totalItemsCount);
@Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
// Don't take any action on changed
}
}
我正在为我的图片库使用 StaggeredGridLayoutManager。我设置了 setReverseLayout(true)
,以便图像从底部堆叠。
我面临的问题是,在应用程序初始化时,滚动条指向图库底部。当用户首次启动应用程序时,我希望滚动条位于图库的顶部。
我试过使用 scrollToPosition
(以下代码片段),但滚动最终出现在画廊中间的某个地方,可能是因为在调用 [= 时图像没有正确加载13=].
mLayoutManager = new StaggeredGridLayoutManager(2,StaggeredGridLayoutManager.VERTICAL);
mLayoutManager.setReverseLayout(true);
mRecyclerView.setLayoutManager(mLayoutManager);
mImageList = ((MainActivity)getActivity()).getImages();
adapter = new ImageAdapter(getActivity(),mImageList);
mRecyclerView.setAdapter(adapter);
mRecyclerView.scrollToPosition(mImageList.size()-1);
是否有正确的方法将滚动条指向顶部,而不是底部?
尝试通过调用找到第一个可见位置 findFirstCompletelyVisibleItemPositions
或findFirstVisibleItemPositions
使用从先前方法获得的位置调用您的回收器视图 scrollToPosition
尝试使用 StaggeredGridLayoutManager
的 scrollToPositionWithOffset()
功能。我发现它比 scrollToPosition
更可靠。还要确保在 Handler().post()
内执行此函数。这将导致 Runnable
被添加到消息队列中。一旦 UI 线程空闲,它将 运行。
new Handler().post(new Runnable() {
@Override
public void run() {
staggeredGridLayoutManager.scrollToPositionWithOffset(mImageList.size() - 1, 0);
}
});
我在 dataobserver 中使用了 scrolltoposition,现在它工作正常..
当 recyclerview 加载时,使用以下代码可以看到顶部的项目:
rcAdapter.registerAdapterDataObserver(new RecyclerView.AdapterDataObserver() {
@Override
public void onItemRangeInserted(int positionStart, int itemCount) {
super.onItemRangeInserted(positionStart, itemCount);
int count = rcAdapter.getItemCount();
mRecyclerView.scrollToPosition(itemCount-1);
}
});
要像在聊天视图中一样滚动到底部以查看新添加的项目,请使用以下代码。
rcAdapter.registerAdapterDataObserver(new RecyclerView.AdapterDataObserver() {
@Override
public void onItemRangeInserted(int positionStart, int itemCount) {
super.onItemRangeInserted(positionStart, itemCount);
int count = rcAdapter.getItemCount();
int lastVisiblePositions[] = new int[2]; //for 2 columns
int lastVisiblePosition = staggeredGridLayoutManager.findLastCompletelyVisibleItemPositions(lastVisiblePositions)[0];
// If the recycler view is initially being loaded or the user is at the bottom of the list, scroll
// to the bottom of the list to show the newly added message.
if (lastVisiblePosition == -1 ||
(positionStart >= (count- 1) && lastVisiblePosition == (positionStart - 1))) {
mRecyclerView.scrollToPosition(positionStart);
}
}
});
我之前解决过类似的问题,这里是方法:
mRecyclerView.getViewTreeObserver().addOnGlobalLayoutListener(
new ViewTreeObserver.OnGlobalLayoutListener() {
@SuppressWarnings("deprecation")
@Override
public void onGlobalLayout() {
ViewTreeObserver observer = mRecyclerView.getViewTreeObserver();
scrollRecyclerViewToTop();
if (!observer.isAlive()) {
return;
}
if (mScrolledByUser) {
if (hasJellyBeanApi()) {
observer.removeOnGlobalLayoutListener(this);
} else {
observer.removeGlobalOnLayoutListener(this);
}
}
}
});
并且:
mRecyclerView.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
mScrollByUser = true;
return false;
}
});
并且:
private void scrollRecyclerViewToTop() {
mRecyclerView.scrollToPosition(0);
mRecyclerView.scrollBy(0, Integer.MIN_VALUE);
}
意思很简单:让RecyclerView
一直滚动到顶部直到用户触摸它。希望对您有所帮助。
这段代码可能对你有帮助,我也在代码
中使用了这个linkhttps://guides.codepath.com/android/Endless-Scrolling-with-AdapterViews-and-RecyclerView
Every AdapterView (such as ListView and GridView) has support for binding to the OnScrollListener events which are triggered whenever a The user scrolls through the collection. Using this system, we can define a basic EndlessScrollListener which supports most use cases by creating our own class that extends OnScrollListener:
public abstract class EndlessScrollListener implements AbsListView.OnScrollListener {
// The minimum number of items to have below your current scroll position
// before loading more.
private int visibleThreshold = 5;
// The current offset index of data you have loaded
private int currentPage = 0;
// The total number of items in the dataset after the last load
private int previousTotalItemCount = 0;
// True if we are still waiting for the last set of data to load.
private boolean loading = true;
// Sets the starting page index
private int startingPageIndex = 0;
public EndlessScrollListener() {
}
public EndlessScrollListener(int visibleThreshold) {
this.visibleThreshold = visibleThreshold;
}
public EndlessScrollListener(int visibleThreshold, int startPage) {
this.visibleThreshold = visibleThreshold;
this.startingPageIndex = startPage;
this.currentPage = startPage;
}
// This happens many times a second during a scroll, so be wary of the code you place here.
// We are given a few useful parameters to help us work out if we need to load some more data,
// but first we check if we are waiting for the previous load to finish.
@Override
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount)
{
// If the total item count is zero and the previous isn't, assume the
// list is invalidated and should be reset back to initial state
if (totalItemCount < previousTotalItemCount) {
this.currentPage = this.startingPageIndex;
this.previousTotalItemCount = totalItemCount;
if (totalItemCount == 0) { this.loading = true; }
}
// If it's still loading, we check to see if the dataset count has
// changed, if so we conclude it has finished loading and update the current page
// number and total item count.
if (loading && (totalItemCount > previousTotalItemCount)) {
loading = false;
previousTotalItemCount = totalItemCount;
currentPage++;
}
// If it isn't currently loading, we check to see if we have breached
// the visibleThreshold and need to reload more data.
// If we do need to reload some more data, we execute onLoadMore to fetch the data.
if (!loading && (firstVisibleItem + visibleItemCount + visibleThreshold) >= totalItemCount ) {
loading = onLoadMore(currentPage + 1, totalItemCount);
}
}
// Defines the process for actually loading more data based on page
// Returns true if more data is being loaded; returns false if there is no more data to load.
public abstract boolean onLoadMore(int page, int totalItemsCount);
@Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
// Don't take any action on changed
}
}