RecyclerView scrollToPosition не запускает scrollListener
Я использую 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);
Слушатель прокрутки не запускается.
Ответы
Ответ 1
Это известная проблема. Это вызвано тем фактом, что RecyclerView не знает, как LayoutManager будет обрабатывать свиток или если он будет обрабатывать его вообще.
В следующем выпуске вы получите вызов onScrolled
, если первая и последняя дочерняя позиция будут изменены после макета (что обычно является результатом вызова прокрутки в позицию).
К сожалению, dx и dy будут равны 0, потому что RecyclerView не знает, сколько прокрутил менеджер макетов для обработки запроса scrollTo
. Кроме того, вы также можете использовать обратный вызов прокрутки ViewTreeObserver.
Ответ 2
Я столкнулся с той же проблемой и нашел обходной путь, который должен использовать smoothScrollToPosition в менеджере компоновки. Этот метод запускает прослушиватель прокрутки. Поэтому в основном это то, что я использую:
recyclerView.scrollToPosition(recyclerAdapter.getItemCount() - 1);
и теперь я изменил это:
recyclerView.getLayoutManager().smoothScrollToPosition(recyclerView, null, recyclerAdapter.getItemCount() - 1);
и он отлично работает для меня.
Ответ 3
Это немного рудиментарно, но вы можете попробовать этот подкласс 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);
}
}
Ответ 4
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
Чтобы явно вызвать onScrollListener над просмотром ресайклера, используйте:
recyclerView.smoothScrollBy(x, y);
//x is the horizontal displacement and y is vertical displacement.
Ответ 6
Я не мог использовать 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
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);
}
});