How to implement load more recyclerview in android

生来就可爱ヽ(ⅴ<●) 提交于 2019-11-30 13:07:15
wsgeorge

I found an answer here that, I believe, is much better than most I've seen on SO and elsewhere.

The idea is simple: in onScrolled in your RecyclerView's ScrollListener, check if the last completely visible item is the last item in your data set.

        if(llm.findLastCompletelyVisibleItemPosition() == data.length() -1){
            //bottom of list!
            loadMoreData();
        }

This happens with a method in the LinearLayoutManager. Calling LinearLayoutManager#findLastCompletelyVisibleItemPosition() can comparing it to the position of the last item in your dataset let's you know when you can load more.

I haven't tried this for the GridLayoutManager.

UPDATE

LinearLayoutManager#findLastVisibleItemPosition() is a better alternative to LinearLayoutManager#findLastCompletelyVisibleItemPosition(), especially when your items are longer than the window height.

This links may help you .for load-moreRrecyclerview you need to change. and implement using Link

or library

Try this....

  static boolean loadmore=true;
  LinearLayoutManager layoutManager = ((LinearLayoutManager)recyclerView.getLayoutManager());
   recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
        @Override
        public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
            // super.onScrolled(recyclerView, dx, dy);
            int lastVisiblePosition = layoutManager.findLastVisibleItemPosition();
            if (lastVisiblePosition == recyclerView.getChildCount()) {
                if (loadmore) {
                    loadmore = false;
                   method();
                }
            }
        }
    });


  private void method(){
      loadmore=true;
  }
import android.support.v7.widget.OrientationHelper;
import android.support.v7.widget.RecyclerView;
import android.view.View;

/**
 * Created by CRAFT BOX on 9/7/2016.
 */
public class RecyclerViewPositionHelper {

    final RecyclerView recyclerView;
    final RecyclerView.LayoutManager layoutManager;

    RecyclerViewPositionHelper(RecyclerView recyclerView) {
        this.recyclerView = recyclerView;
        this.layoutManager = recyclerView.getLayoutManager();
    }

    public static RecyclerViewPositionHelper createHelper(RecyclerView recyclerView) {
        if (recyclerView == null) {
            throw new NullPointerException("Recycler View is null");
        }
        return new RecyclerViewPositionHelper(recyclerView);
    }

    /**
     * Returns the adapter item count.
     *
     * @return The total number on items in a layout manager
     */
    public int getItemCount() {
        return layoutManager == null ? 0 : layoutManager.getItemCount();
    }

    /**
     * Returns the adapter position of the first visible view. This position does not include
     * adapter changes that were dispatched after the last layout pass.
     *
     * @return The adapter position of the first visible item or {@link RecyclerView#NO_POSITION} if
     * there aren't any visible items.
     */
    public int findFirstVisibleItemPosition() {
        final View child = findOneVisibleChild(0, layoutManager.getChildCount(), false, true);
        return child == null ? RecyclerView.NO_POSITION : recyclerView.getChildAdapterPosition(child);
    }

    /**
     * Returns the adapter position of the first fully visible view. This position does not include
     * adapter changes that were dispatched after the last layout pass.
     *
     * @return The adapter position of the first fully visible item or
     * {@link RecyclerView#NO_POSITION} if there aren't any visible items.
     */
    public int findFirstCompletelyVisibleItemPosition() {
        final View child = findOneVisibleChild(0, layoutManager.getChildCount(), true, false);
        return child == null ? RecyclerView.NO_POSITION : recyclerView.getChildAdapterPosition(child);
    }

    /**
     * Returns the adapter position of the last visible view. This position does not include
     * adapter changes that were dispatched after the last layout pass.
     *
     * @return The adapter position of the last visible view or {@link RecyclerView#NO_POSITION} if
     * there aren't any visible items
     */
    public int findLastVisibleItemPosition() {
        final View child = findOneVisibleChild(layoutManager.getChildCount() - 1, -1, false, true);
        return child == null ? RecyclerView.NO_POSITION : recyclerView.getChildAdapterPosition(child);
    }

    /**
     * Returns the adapter position of the last fully visible view. This position does not include
     * adapter changes that were dispatched after the last layout pass.
     *
     * @return The adapter position of the last fully visible view or
     * {@link RecyclerView#NO_POSITION} if there aren't any visible items.
     */
    public int findLastCompletelyVisibleItemPosition() {
        final View child = findOneVisibleChild(layoutManager.getChildCount() - 1, -1, true, false);
        return child == null ? RecyclerView.NO_POSITION : recyclerView.getChildAdapterPosition(child);
    }

    View findOneVisibleChild(int fromIndex, int toIndex, boolean completelyVisible,
                             boolean acceptPartiallyVisible) {
        OrientationHelper helper;
        if (layoutManager.canScrollVertically()) {
            helper = OrientationHelper.createVerticalHelper(layoutManager);
        } else {
            helper = OrientationHelper.createHorizontalHelper(layoutManager);
        }

        final int start = helper.getStartAfterPadding();
        final int end = helper.getEndAfterPadding();
        final int next = toIndex > fromIndex ? 1 : -1;
        View partiallyVisible = null;
        for (int i = fromIndex; i != toIndex; i += next) {
            final View child = layoutManager.getChildAt(i);
            final int childStart = helper.getDecoratedStart(child);
            final int childEnd = helper.getDecoratedEnd(child);
            if (childStart < end && childEnd > start) {
                if (completelyVisible) {
                    if (childStart >= start && childEnd <= end) {
                        return child;
                    } else if (acceptPartiallyVisible && partiallyVisible == null) {
                        partiallyVisible = child;
                    }
                } else {
                    return child;
                }
            }
        }
        return partiallyVisible;
    }
}

/* NearbyModel */



/**
 * Created by CRAFT BOX on 8/23/2016.
 */
public class NearbyModel {

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getRate() {
        return rate;
    }

    public void setRate(String rate) {
        this.rate = rate;
    }
    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }

    public String getImage_path() {
        return image_path;
    }

    public void setImage_path(String image_path) {
        this.image_path = image_path;
    }

    String id;
    String name;
    String rate;

    public String getDistance() {
        return distance;
    }

    public void setDistance(String distance) {
        this.distance = distance;
    }

    String distance;


    public String getReview() {
        return review;
    }

    public void setReview(String review) {
        this.review = review;
    }

    String review;
    String address;

    public String getCategory_name() {
        return category_name;
    }

    public void setCategory_name(String category_name) {
        this.category_name = category_name;
    }

    String category_name;
    String image_path;
    public NearbyModel()
    {

    }
    public NearbyModel(String id,String name,String rate,String distance,String review,String address,String category_name,String image_path)
    {
        this.id=id;
        this.name=name;
        this.rate=rate;
        this.distance=distance;
        this.review=review;
        this.address=address;
        this.category_name=category_name;
        this.image_path=image_path;
    }

}



 /* My activity */

 public class Search_by_shop extends Fragment {


    private RecyclerView recyclerView;
    ArrayList<NearbyModel> near_data;
    NearAdapter adapter;

    int firstVisibleItem, visibleItemCount, totalItemCount,count=0;
    protected int m_PreviousTotalCount;
    RecyclerViewPositionHelper mRecyclerViewHelper;


     @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,Bundle savedInstanceState)
    {
        View rootView = inflater.inflate(R.layout.search_by_shop_fragment, container, false);
        recyclerView = (RecyclerView) rootView.findViewById(R.id.search_by_recycleview);

        recyclerView.setOnScrollListener(new RecyclerView.OnScrollListener() {
            @Override
            public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
                super.onScrollStateChanged(recyclerView, newState);

                mRecyclerViewHelper = RecyclerViewPositionHelper.createHelper(recyclerView);
                visibleItemCount = recyclerView.getChildCount();
                totalItemCount = mRecyclerViewHelper.getItemCount();
                firstVisibleItem = mRecyclerViewHelper.findFirstVisibleItemPosition();

                if (totalItemCount == 0 || adapter == null)
                    return;
                if (m_PreviousTotalCount == totalItemCount)
                {
                    return;
                }
                else
                {
                    boolean loadMore = firstVisibleItem + visibleItemCount >= totalItemCount;
                    if (loadMore)
                    {
                        m_PreviousTotalCount = totalItemCount;
                        new GetAllrestaurant().execute();
                    }
                }
            }
        });

        new GetAllrestaurant().execute();

        return rootView;
   }

   public class GetAllrestaurant extends AsyncTask<String, Void, JSONObject> {
        ProgressDialog pd;
        @Override
        protected void onPreExecute() {
            super.onPreExecute();
            pd = new ProgressDialog(getActivity());
            pd.setTitle("Please Wait");
            pd.setMessage("Loading");
            pd.setCancelable(false);
            pd.show();
        }

        @Override
        protected JSONObject doInBackground(String... strings) {
            UserFunction uf = new UserFunction();
            JSONObject json = uf.getAllrestaurunt();
            return json;
        }

        @Override
        protected void onPostExecute(JSONObject json) {
            super.onPostExecute(json);
            pd.dismiss();
            try {
                if (json.getInt("ack") == 1) {
                    JSONArray json_users = json.getJSONArray("result");
                    // looping through All Products
                    for (int i = 0; i < json_users.length(); i++) {
                        JSONObject c = json_users.getJSONObject(i);
                        String id = c.getString("id");
                        String name = c.getString("name");
                        String distance = c.getString("distance");
                        String category = c.getString("serving_category");
                        String rate = c.getString("rate");
                        String address = c.getString("address");
                        String count_review = c.getString("count_review");
                        String image_path = c.getString("image_path");
                        NearbyModel da=new NearbyModel(id,name,rate,distance,count_review,address,category,image_path);
                        near_data.add(da);
                    }

                    if(count==0)
                    {
                        adapter = new NearAdapter(getActivity(), near_data);
                        recyclerView.setAdapter(adapter);
                        recyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
                    }
                    else
                    {
                        adapter.notifyDataSetChanged();
                    }
                    if(json_users.length()==0)
                    {
                        count=0;
                    }
                    else
                    {
                        count+=json_users.length();
                    }

                }
            } catch (Exception e) {
                Log.e("<-SubjectActException->", e.toString());
            }
        }
    }

    public class NearAdapter extends RecyclerView.Adapter<NearAdapter.ViewHolder> {
        private ArrayList<NearbyModel> data;
        private Context context;
        public NearAdapter(Context context,ArrayList<NearbyModel> data) {
            this.data = data;
            this.context = context;
        }

        @Override
        public ViewHolder onCreateViewHolder(ViewGroup viewGroup, final int i) {
            View view = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.list_near_by, viewGroup, false);
            return new ViewHolder(view);
        }

        @Override
        public void onBindViewHolder(ViewHolder viewHolder, final int i) {
            viewHolder.name.setText(data.get(i).getName());
            viewHolder.distince.setText(data.get(i).getDistance());
            viewHolder.review.setText(data.get(i).getReview());
            viewHolder.category.setText(data.get(i).getCategory_name());
            viewHolder.address.setText(data.get(i).getAddress());
            viewHolder.rat.setRating(Integer.parseInt(data.get(i).getRate()));
            viewHolder.vi_click.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    GlobalVariable.position=i;
                    Intent ik=new Intent(context,Restaurant_detail.class);
                    ik.putExtra("rid",""+data.get(i).getId());
                    startActivity(ik);
                }
            });
            if(data.get(i).getImage_path().equals(""))
            {
                Picasso.with(context).load("abc").placeholder(R.drawable.load_240).into(viewHolder.img);
            }
            else
            {
                Picasso.with(context).load(data.get(i).getImage_path()).placeholder(R.drawable.load_240).into(viewHolder.img);
            }
        }

        @Override
        public int getItemCount() {
            return data.size();
        }

        public class ViewHolder extends RecyclerView.ViewHolder{
            private TextView name,distince,review,category,address;
            private ImageView img;
            private RatingBar rat;
            CardView vi_click;

            public ViewHolder(View view) {
                super(view);
                name = (TextView)view.findViewById(R.id.list_near_by_name);
                distince = (TextView)view.findViewById(R.id.list_near_by_distince);
                review = (TextView)view.findViewById(R.id.list_near_by_review);
                category = (TextView)view.findViewById(R.id.list_near_by_category);
                address = (TextView)view.findViewById(R.id.list_near_by_address);
                img = (ImageView) view.findViewById(R.id.list_near_by_img);
                rat = (RatingBar)view.findViewById(R.id.list_near_by_ratbar);
                vi_click = (CardView)view.findViewById(R.id.list_near_card);
            }
        }
    }

You can check this link for Load More RecyclerView and Bottom ProgressBar.

I have created a commonAdapter to handle loadMore

public abstract class CommonModelAdapter<T,V extends BaseModelViewHolder<T>> extends RecyclerView.Adapter<V>{

    public abstract V setViewHolder(ViewGroup parent);

    private Context mContext;
    private List<T> items;
    private List<T> copyItems;

    public static final int VIEW_TYPE_PROGRESS = 0;
    public static final int VIEW_TYPE_ITEM = 1;

    public CommonModelAdapter(Context mContext,List<T> items){
        this.mContext = mContext;
        this.items = items;
        copyItems = new ArrayList<>();
        copyItems.addAll(items);
    }

    @Override
    public V onCreateViewHolder(ViewGroup parent, int viewType) {
        if(viewType == VIEW_TYPE_ITEM){
            return setViewHolder(parent);
        }
        else{
            return (V) new ProgressViewHolder(parent ,R.layout.item_progress_loader);
        }
    }

    @Override
    public void onBindViewHolder(V holder, int position) {
        if (holder instanceof ProgressViewHolder) {
            ((ProgressViewHolder) holder).showProgressLoader();
        }
        else{
            try {
                holder.onBindData(items.get(position));
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    @Override
    public int getItemCount() {
        return items.size();
    }

    @Override
    public int getItemViewType(int position) {
        if(items.get(position) == null)
            return VIEW_TYPE_PROGRESS;
        else
            return VIEW_TYPE_ITEM;
    }

    public T getItemAt(int position){
        return items.get(position);
    }

    public void setItems(List<T> newItems){
        this.items = newItems;
    }
}

Where BaseModelViewHolder

public abstract class BaseModelViewHolder<T extends BaseModelBO> extends RecyclerView.ViewHolder {

    public abstract void onBindData(T data);

    public BaseModelViewHolder(ViewGroup parent, int layoutId) {
        super(LayoutInflater.from(parent.getContext()).inflate(layoutId, parent, false));
    }

    public <T extends View> T findViewById(@IdRes int resId) {
        return (T) itemView.findViewById(resId);
    }
}

LoadMoreRecyclerView

public class LoadMoreRecyclerView extends RecyclerView  {

    private boolean loading = true;
    int pastVisiblesItems, visibleItemCount, totalItemCount;
    //WrapperLinearLayout is for handling crash in RecyclerView
    private WrapperLinearLayout mLayoutManager;
    private Context mContext;
    private OnLoadMoreListener onLoadMoreListener;

    public LoadMoreRecyclerView(Context context) {
        super(context);
        mContext = context;
        init();
    }

    public LoadMoreRecyclerView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        mContext = context;
        init();
    }

    public LoadMoreRecyclerView(Context context, @Nullable AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        mContext = context;
        init();
    }

    private void init(){
        mLayoutManager = new WrapperLinearLayout(mContext,LinearLayoutManager.VERTICAL,false);
        this.setLayoutManager(mLayoutManager);
        this.setItemAnimator(new DefaultItemAnimator());
        this.setHasFixedSize(true);
    }

    @Override
    public void onScrolled(int dx, int dy) {
        super.onScrolled(dx, dy);

        if(dy > 0) //check for scroll down
        {
            visibleItemCount = mLayoutManager.getChildCount();
            totalItemCount = mLayoutManager.getItemCount();
            pastVisiblesItems = mLayoutManager.findFirstVisibleItemPosition();

            if (loading)
            {
                if ( (visibleItemCount + pastVisiblesItems) >= totalItemCount)
                {
                    loading = false;
                    Log.v("...", "Call Load More !");
                    if(onLoadMoreListener != null){
                        onLoadMoreListener.onLoadMore();
                    }
                    //Do pagination.. i.e. fetch new data
                }
            }
        }
    }

    @Override
    public void onScrollStateChanged(int state) {
        super.onScrollStateChanged(state);
    }

    public void enableLoadingMore(boolean moreLoading){
        loading = moreLoading;
    }

    public void setOnLoadMoreListener(OnLoadMoreListener onLoadMoreListener) {
        this.onLoadMoreListener = onLoadMoreListener;
    }

    public void setScrolling(boolean enable){
        mLayoutManager.setScrollEnabled(enable);
    }
}

When you want to show progress...

 mLoadMoreRecyclerView.setOnLoadMoreListener(new OnLoadMoreListener() {
        @Override
        public void onLoadMore() {

            {
                overAllItems.add(null); //to show ProgressDialog
                mAdapter.notifyDataSetChanged();

                callYourService();
            }
            /*else{
                //for reEnable calling it...
                mLoadMoreRecyclerView.enableLoadingMore(true);
            }*/

        }
    });
public abstract class LoadMoreAdapter extends RecyclerView.Adapter{
private LoadMoreListner loadMoreListner;
private boolean isLoading;
int vissibleThreshold = 5;

public LoadMoreAdapter(final LoadMoreListner loadMoreListner, RecyclerView recyclerView) {
    this.loadMoreListner = loadMoreListner;
    final LinearLayoutManager linearLayoutManager = (LinearLayoutManager) recyclerView.getLayoutManager();
    recyclerView.addOnScrollListener(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);
            int totalItemCOunt = linearLayoutManager.getItemCount();
            int lastVissibleItemPOs = linearLayoutManager.findLastVisibleItemPosition();
            if (!isLoading && totalItemCOunt<= lastVissibleItemPOs+vissibleThreshold){
                if (loadMoreListner!=null){
                    isLoading = true;
                    loadMoreListner.onLoadMore();
                }
            }
        }
    });
}
public void setLoaded(){
    isLoading =false;
}

}

Your adapter will extends to this LoadmoreAdapter

public interface LoadMoreListner {
void onLoadMore();

}

And in your activity

@Override
public void onLoadMore() {
    items.add(null);
    nameLoadMoreAdapter.notifyItemInserted(items.size()-1);
    loadNewData();
}

After populating list and here your loadnewData() will have this

items.remove(items.size()-1);
            nameLoadMoreAdapter.notifyItemRemoved(items.size());
            items.addAll(itemsArrayList);
            nameLoadMoreAdapter.notifyItemInserted(items.size());
            nameLoadMoreAdapter.setLoaded();

where itemsArrayList are of newdata

Check do you currently have items to scroll down -

if (! recyclerView.canScrollVertically(1))

If yes - load more items, for example, using HTTP client.

Full code:

recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
            @Override
            public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) {
                super.onScrolled(recyclerView, dx, dy);
                if (! recyclerView.canScrollVertically(1)){ //1 for down
                    loadMore();
                }
            }
        });
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!