我正在使用RecyclerView,ScrollListener:
mRecyclerView.setOnScrollListener(new RecyclerView.OnScrollListener()
{
@Override
public void onScrollStateChanged(RecyclerView recyclerView, int newState)
{
super.onScrollStateChanged(recyclerView, newState);
}
@Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy)
{
super.onScrolled(recyclerView, dx, dy);
// Do my logic
}
});
当我用手指滚动时,滚动侦听器触发了。
但是当我逐步滚动时,就像那样:
mRecyclerView.scrollToPosition(LAST_POSITION);
不会触发滚动侦听器。
答案 0 :(得分:23)
这是一个已知问题。这是因为RecyclerView不知道LayoutManager如何处理滚动或它是否会处理它。
在下一个版本中,如果布局后的第一个或最后一个子位置发生变化(通常是调用滚动到位置的结果),您将收到onScrolled
的调用。
不幸的是,dx和dy将为0,因为RecyclerView并不真正知道布局管理器确实滚动了多少来处理scrollTo
请求。或者,您也可以使用ViewTreeObserver的滚动回调。
答案 1 :(得分:23)
我遇到了同样的问题并找到了一种解决方法,即在布局管理器中使用smoothScrollToPosition。此方法触发滚动侦听器。基本上这就是我用来拥有的东西:
recyclerView.scrollToPosition(recyclerAdapter.getItemCount() - 1);
现在我改为:
recyclerView.getLayoutManager().smoothScrollToPosition(recyclerView, null, recyclerAdapter.getItemCount() - 1);
它对我来说很好。
答案 2 :(得分:0)
它有点简陋,但你可以试试这个RecyclerView的子类:
public class PatchedRecyclerView extends RecyclerView {
private OnScrollListener listener;
public PatchedRecyclerView(Context context) {
super(context);
}
public PatchedRecyclerView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public PatchedRecyclerView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
@Override
public void setOnScrollListener(OnScrollListener listener) {
super.setOnScrollListener(listener);
this.listener = listener;
}
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
int preFirstChildPosition = getChildCount() != 0 ? getChildViewHolder(getChildAt(0)).getPosition() : -1;
int preLastChildPosition = getChildCount() != 0 ? getChildViewHolder(getChildAt(getChildCount() - 1)).getPosition() : -1;
super.onLayout(changed, l, t, r, b);
int postFirstChildPosition = getChildCount() != 0 ? getChildViewHolder(getChildAt(0)).getPosition() : -1;
int postLastChildPosition = getChildCount() != 0 ? getChildViewHolder(getChildAt(getChildCount() - 1)).getPosition() : -1;
// TODO: Insert proper DX and DY values
if (preFirstChildPosition != postFirstChildPosition || preLastChildPosition != postLastChildPosition)
listener.onScrolled(this, 0, 0);
}
}
答案 3 :(得分:0)
Muito legal seu conselho。
Button maisOpcoes = (Button) findViewById(R.id.maisOpcoes);
maisOpcoes.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
recyclerView.getLayoutManager().smoothScrollToPosition(recyclerView, null , recyclerViewTmd.getItemCount() - 1);
maisOpcoes.setVisibility(View.GONE);
}
});
答案 4 :(得分:0)
int mFirst=0, mLast=0;
recyclerview.setOnScrollListener(new RecyclerView.OnScrollListener() {
@Override
public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
super.onScrollStateChanged(recyclerView, newState);
}
@Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
LinearLayoutManager llm = (LinearLayoutManager) recyclerview.getLayoutManager();
mLast = llm.findLastCompletelyVisibleItemPosition();
mFirst = llm.findFirstCompletelyVisibleItemPosition();
}
});
imgRight.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
LinearLayoutManager llm = (LinearLayoutManager) recyclerview.getLayoutManager();
llm.scrollToPositionWithOffset(mLast + 1, List.length());
}
});
imgLeft.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
LinearLayoutManager llm = (LinearLayoutManager) recyclerview.getLayoutManager();
llm.scrollToPositionWithOffset(mFirst - 1, List.length());
}
});
答案 5 :(得分:0)
要通过回收站视图显式触发onScrollListener,请使用:
recyclerView.smoothScrollBy(x, y);
//x is the horizontal displacement and y is vertical displacement.
答案 6 :(得分:0)
我无法使用smoothScrollToPosition(过去我们遇到了一些问题)并且取决于第一项的位置似乎不可靠,所以我最终使用了yigit的答案(已经发布了)已经),不幸的是它并不总是有用(我不确定为什么)。
所以我最后使用了我之前添加到RecyclerView的滚动监听器,遗憾的是我无法找到此解决方案的来源。
如果你需要一个常量的话我不认为你应该使用这个监听器,幸运的是我只需要在特定的时间听。
覆盖RecyclerView:
public class MyRecyclerView extends RecyclerView {
public interface OnScrollStoppedListener{
void onScrollStopped();
}
private static final int NEW_CHECK_INTERVAL = 100;
private OnScrollStoppedListener mOnScrollStoppedListener;
private Runnable mScrollerTask;
private int mInitialPosition;
public MyRecyclerView(Context context) {
super(context);
init();
}
public MyRecyclerView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
init();
}
public MyRecyclerView(Context context, @Nullable AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init();
}
private void init() {
mScrollerTask = new Runnable() {
public void run() {
int newPosition = getScrollY();
if(mInitialPosition - newPosition == 0) {//has stopped
if(mOnScrollStoppedListener !=null) {
mOnScrollStoppedListener.onScrollStopped();
}
} else {
startScrollerTask();
}
}
};
}
public void setOnScrollStoppedListener(MyRecyclerView.OnScrollStoppedListener listener){
mOnScrollStoppedListener = listener;
}
public void startScrollerTask() {
mInitialPosition = getScrollY();
postDelayed(mScrollerTask, NEW_CHECK_INTERVAL);
}
}
用法:
myRecyclerView.setOnScrollStoppedListener(new MyRecyclerView.OnScrollStoppedListener() {
@Override
public void onScrollStopped() {
// Do your thing
}
});
myRecyclerView.startScrollerTask();
答案 7 :(得分:0)
请尝试
LinearLayoutManager.scrollToPositionWithOffset(int, int).
LayoutManager.scrollToPosition()
可能效果不佳,但LinearLayoutManager.scrollToPositionWithOffset()
可行。和类似的GridLayoutManager一样。
或者我们必须编写自定义的实现方式,因为RecyclerView不知道LayoutManager如何滚动视图。
class CustomLayoutManager extends LinearLayoutManager{
public void smoothScrollToPosition(RecyclerView recyclerView,
RecyclerView.State state, final int position) {
LinearSmoothScroller smoothScroller =
new LinearSmoothScroller(mContext) {
//Override the methods and write your implementation as per your requirement
//one which controls the direction and another one calculate the speed per Pixel
}
}
有时这就是诀窍
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
yourList.scrollToPosition(position);
}
}, 200);