davideas / FlexibleAdapter

Fast and versatile Adapter for RecyclerView which regroups several features into one library to considerably improve the user experience :-)
Apache License 2.0
3.55k stars 548 forks source link

fastScroller will not update the location at some time #695

Closed tcqq closed 5 years ago

tcqq commented 5 years ago

@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 beforetim 20181118200649Scroll after tim 20181118201526

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);
    }
}
tcqq commented 5 years ago

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 commented 5 years ago

Linked with #686.