@davideas When I use recyclerView + loadMore + fastScroller in the Activity. When loadMore successfully, the position of fastScroller is not automatically updated. Only after the list is scroll the location of fastScroller will updated. How can I fix this?
Here are the screenshots and code. Code can be copied directly into the example to running and reproduce this issue.
Scroll beforeScroll after
Code:
package eu.davidea.samples.flexibleadapter;
import android.os.Bundle;
import android.os.Handler;
import android.util.Log;
import android.widget.Toast;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Random;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.RecyclerView;
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
import eu.davidea.fastscroller.FastScroller;
import eu.davidea.flexibleadapter.FlexibleAdapter;
import eu.davidea.flexibleadapter.common.SmoothScrollLinearLayoutManager;
import eu.davidea.flexibleadapter.helpers.EmptyViewHelper;
import eu.davidea.flexibleadapter.items.AbstractFlexibleItem;
import eu.davidea.samples.flexibleadapter.animators.FadeInDownItemAnimator;
import eu.davidea.samples.flexibleadapter.items.ProgressItem;
import eu.davidea.samples.flexibleadapter.items.ScrollableLayoutItem;
import eu.davidea.samples.flexibleadapter.services.DatabaseConfiguration;
import eu.davidea.samples.flexibleadapter.services.DatabaseService;
public class EndlessScrollingActivity extends AppCompatActivity implements
FastScroller.OnScrollStateChangeListener,
FlexibleAdapter.EndlessScrollListener {
public static final String TAG = EndlessScrollingActivity.class.getSimpleName();
private RecyclerView mRecyclerView;
private ExampleAdapter mAdapter;
private ProgressItem mProgressItem = new ProgressItem();
@Override
public void onSaveInstanceState(Bundle outState) {
mAdapter.onSaveInstanceState(outState);
super.onSaveInstanceState(outState);
}
@Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
// Restore previous state
if (savedInstanceState != null && mAdapter != null) {
// Selection
mAdapter.onRestoreInstanceState(savedInstanceState);
}
}
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.fragment_recycler_view);
// Create New Database and Initialize RecyclerView
if (savedInstanceState == null) {
DatabaseService.getInstance().createHeadersSectionsDatabase(0, 0); //N. of items
}
initializeRecyclerView(savedInstanceState);
}
private void initializeRecyclerView(Bundle savedInstanceState) {
// Initialize Adapter and RecyclerView
// ExampleAdapter makes use of stableIds, I strongly suggest to implement 'item.hashCode()'
FlexibleAdapter.useTag("EndlessScrollingAdapter");
if (savedInstanceState != null) {
mAdapter = new ExampleAdapter(DatabaseService.getInstance().getDatabaseList(), this);
} else {
mAdapter = new ExampleAdapter(null, this);
}
mAdapter.setAutoScrollOnExpand(true)
//.setAnimateToLimit(Integer.MAX_VALUE) //Use the default value
.setNotifyMoveOfFilteredItems(true) //When true, filtering on big list is very slow, not in this case!
.setNotifyChangeOfUnfilteredItems(true) //true by default
.setAnimationOnForwardScrolling(DatabaseConfiguration.animateOnForwardScrolling)
.setAnimationOnReverseScrolling(true);
mRecyclerView = findViewById(R.id.recycler_view);
mRecyclerView.setLayoutManager(new SmoothScrollLinearLayoutManager(this));
mRecyclerView.setAdapter(mAdapter);
mRecyclerView.setHasFixedSize(true); //Size of RV will not change
// NOTE: Use the custom FadeInDownAnimator for ALL notifications for ALL items,
// but ScrollableFooterItem implements AnimatedViewHolder with a unique animation: SlideInUp!
mRecyclerView.setItemAnimator(new FadeInDownItemAnimator());
// Add FastScroll to the RecyclerView, after the Adapter has been attached the RecyclerView!!!
FastScroller fastScroller = findViewById(R.id.fast_scroller);
fastScroller.addOnScrollStateChangeListener(this);
mAdapter.setFastScroller(fastScroller);
// New empty views handling, to set after FastScroller
EmptyViewHelper.create(mAdapter,
findViewById(R.id.empty_view),
findViewById(R.id.filter_view));
mAdapter.setLongPressDragEnabled(true) //Enable long press to drag items
.setHandleDragEnabled(true) //Enable drag using handle view
.setSwipeEnabled(true); //Enable swipe items
SwipeRefreshLayout swipeRefreshLayout = findViewById(R.id.swipeRefreshLayout);
swipeRefreshLayout.setEnabled(true);
// mListener.onFragmentChange(swipeRefreshLayout, mRecyclerView, Mode.IDLE);
// EndlessScrollListener - OnLoadMore (v5.0.0)
mAdapter.setLoadingMoreAtStartUp(savedInstanceState == null) //To call only if the list is empty
//.setEndlessPageSize(3) //Endless is automatically disabled if newItems < 3
//.setEndlessTargetCount(15) //Endless is automatically disabled if totalItems >= 15
.setEndlessScrollThreshold(20) //Default=1
.setEndlessScrollListener(this, mProgressItem)
.setTopEndless(false);
// Add 1 Header item
ScrollableLayoutItem scrollHeader = new ScrollableLayoutItem("SLI");
scrollHeader.setTitle("Endless Scrolling");
scrollHeader.setSubtitle("...with ScrollableHeaderItem");
mAdapter.addScrollableHeader(scrollHeader);
}
@Override
public void noMoreLoad(int newItemsSize) {
}
@Override
public void onLoadMore(final int lastPosition, int currentPage) {
// We don't want load more items when searching into the current Collection!
// Alternatively, for a special filter, if we want load more items when filter is active, the
// new items that arrive from remote, should be already filtered, before adding them to the Adapter!
if (mAdapter.hasFilter()) {
mAdapter.onLoadMoreComplete(null);
return;
}
// Simulating asynchronous call
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
final List<eu.davidea.flexibleadapter.items.AbstractFlexibleItem> newItems = new ArrayList<>();
// 1. Simulating success/failure with Random
int count = new Random().nextInt(200);
int totalItemsOfType = mAdapter.getItemCountOfTypes(R.layout.recycler_simple_item);
for (int i = 1; i <= count; i++) {
newItems.add(DatabaseService.newSimpleItem(totalItemsOfType + i, null));
}
// 2. Callback the Adapter to notify the change:
// - New items will be added to the end of the main list
// - When list is null or empty and limits are reached, Endless scroll will be disabled.
// To enable again, you must call setEndlessProgressItem(@Nullable T progressItem).
if (mAdapter.isTopEndless()) {
Collections.reverse(newItems);
DatabaseService.getInstance().addAll(0, newItems);
} else {
DatabaseService.getInstance().addAll(newItems);
}
mAdapter.onLoadMoreComplete(newItems, (newItems.isEmpty() ? -1 : 3000L));
// - Retrieve the new page number after adding new items!
Log.d(TAG, "LastPosition=" + lastPosition);
Log.d(TAG, "EndlessCurrentPage=" + mAdapter.getEndlessCurrentPage());
Log.d(TAG, "EndlessPageSize=" + mAdapter.getEndlessPageSize());
Log.d(TAG, "EndlessTargetCount=" + mAdapter.getEndlessTargetCount());
// 3. If you have new Expandable and you want expand them, do as following:
// Note: normal items are automatically skipped/ignored because they do not
// implement IExpandable interface! So don't care about them.
for (AbstractFlexibleItem item : newItems) {
// Option A. (Best use case) Initialization is performed:
// - Expanded status is ignored. WARNING: possible subItems duplication!
// - Automatic scroll is skipped
mAdapter.expand(item, true);
// Option B. Simple expansion is performed:
// - WARNING: Automatic scroll is performed!
//mAdapter.expand(item);
}
// 4. Notify user
if (this != null && newItems.size() > 0) {
Toast.makeText(getApplicationContext(),
"Simulated: " + newItems.size() + " new items arrived :-)",
Toast.LENGTH_SHORT).show();
}
}
}, 2000L);
}
@Override
public void onFastScrollerStateChange(boolean scrolling) {
Log.d(TAG, "scrolling: " + scrolling);
}
}
The same code. If directly use the RecyclerView-FastScroll library, the above problem will be fixed. However, when dragging the handle. Drop frame is obvious.
@davideas When I use recyclerView + loadMore + fastScroller in the Activity. When loadMore successfully, the position of fastScroller is not automatically updated. Only after the list is scroll the location of fastScroller will updated. How can I fix this?
Here are the screenshots and code. Code can be copied directly into the example to running and reproduce this issue.
Scroll beforeScroll after
Code: