recyclerview staggeredgridlayoutmanager加载更多进度条

时间:2018-07-26 06:26:17

标签: android android-recyclerview android-progressbar endlessscroll

我在布局中具有 recyclerview

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:baselineAligned="false"
    android:orientation="vertical">

    <android.support.v7.widget.RecyclerView
        android:id="@+id/advertising_list_view_right"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1"
        android:divider="@null"
        android:dividerHeight="0dp"
        android:scrollbars="none" />

    <TextView
        android:id="@+id/empty_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:gravity="center"
        android:text="@string/no_records"
        android:visibility="gone" />

</LinearLayout>

我的 CustomAdapter 是:

public class CustomAdapter extends RecyclerView.Adapter<CustomAdapter.CustomViewHolder> {

private final List<Ad> dataList;
private final Context context;

CustomAdapter(Context context, List<Ad> dataList) {
    this.context = context;
    this.dataList = dataList;
}

class CustomViewHolder extends RecyclerView.ViewHolder {

    final View mView;

    private final TextView adTitle;
    private final TextView adLocation;
    private final TextView adPrice;
    private final ImageView coverImage;

    CustomViewHolder(View itemView) {
        super(itemView);
        mView = itemView;

        adTitle = mView.findViewById(R.id.title);
        adLocation = mView.findViewById(R.id.text_view_key_4);
        adPrice = mView.findViewById(R.id.price_text_view);
        coverImage = mView.findViewById(R.id.company_image_view);
        coverImage.layout(0, 0, 0, 0);
    }
}

@NonNull
@Override
public CustomViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
    LayoutInflater layoutInflater = LayoutInflater.from(parent.getContext());
    View view = layoutInflater.inflate(R.layout.advertising_list_item, parent, false);
    return new CustomViewHolder(view);
}

@Override
public void onBindViewHolder(@NonNull CustomViewHolder holder, int position) {
    holder.adTitle.setText(dataList.get(position).getTitle());
    holder.adLocation.setText(dataList.get(position).getParish());
    if (dataList.get(position).getPrice().length() == 0) {
        holder.adPrice.setText(R.string.agreement);
    } else {
        holder.adPrice.setText(dataList.get(position).getPrice() + " تومان");
    }

    GlideApp.with(context)
            .load(dataList.get(position).getPicture())
            .error(R.drawable.default_pic)
            .diskCacheStrategy(DiskCacheStrategy.ALL)
            .override(dataList.get(position).getPictureWidth(), dataList.get(position).getPictureHeight())
            .placeholder(R.drawable.default_pic)
            .centerCrop()
            .into(holder.coverImage);


}

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

}

为了使我的 recyclerview 永无止境,我使用了此类:

abstract class EndlessRecyclerViewScrollListener extends RecyclerView.OnScrollListener {
// The minimum amount of items to have below your current scroll position
// before loading more.
private int visibleThreshold = 1;
// The current offset index of data you have loaded
private int currentPage = 0;
// The total number of items in the dataset after the last load
private int previousTotalItemCount = 0;
// True if we are still waiting for the last set of data to load.
private boolean loading = true;
// Sets the starting page index
private final int startingPageIndex = 0;


private RecyclerView.LayoutManager mLayoutManager;

public EndlessRecyclerViewScrollListener(LinearLayoutManager layoutManager) {
    this.mLayoutManager = layoutManager;
}

public EndlessRecyclerViewScrollListener(GridLayoutManager layoutManager) {
    this.mLayoutManager = layoutManager;
    visibleThreshold = visibleThreshold * layoutManager.getSpanCount();
}

public EndlessRecyclerViewScrollListener(StaggeredGridLayoutManager layoutManager) {
    this.mLayoutManager = layoutManager;
    visibleThreshold = visibleThreshold * layoutManager.getSpanCount();
}

private int getLastVisibleItem(int[] lastVisibleItemPositions) {
    int maxSize = 0;
    for (int i = 0; i < lastVisibleItemPositions.length; i++) {
        if (i == 0) {
            maxSize = lastVisibleItemPositions[i];
        } else if (lastVisibleItemPositions[i] > maxSize) {
            maxSize = lastVisibleItemPositions[i];
        }
    }
    return maxSize;
}

// This happens many times a second during a scroll, so be wary of the code you place here.
// We are given a few useful parameters to help us work out if we need to load some more data,
// but first we check if we are waiting for the previous load to finish.
@Override
public void onScrolled(RecyclerView view, int dx, int dy) {
    int lastVisibleItemPosition = 0;

    int totalItemCount = mLayoutManager.getItemCount();

    if (mLayoutManager instanceof StaggeredGridLayoutManager) {

        int[] lastVisibleItemPositions = ((StaggeredGridLayoutManager) mLayoutManager).findLastVisibleItemPositions(null);
        // get maximum element within the list
        lastVisibleItemPosition = getLastVisibleItem(lastVisibleItemPositions);
    } else if (mLayoutManager instanceof GridLayoutManager) {

        lastVisibleItemPosition = ((GridLayoutManager) mLayoutManager).findLastVisibleItemPosition();
    } else if (mLayoutManager instanceof LinearLayoutManager) {

        lastVisibleItemPosition = ((LinearLayoutManager) mLayoutManager).findLastVisibleItemPosition();
    }

    // If the total item count is zero and the previous isn't, assume the
    // list is invalidated and should be reset back to initial state
    if (totalItemCount < previousTotalItemCount) {

        this.currentPage = this.startingPageIndex;
        this.previousTotalItemCount = totalItemCount;
        if (totalItemCount == 0) {

            this.loading = true;
        }
    }
    // If it’s still loading, we check to see if the dataset count has
    // changed, if so we conclude it has finished loading and update the current page
    // number and total item count.
    if (loading && (totalItemCount > previousTotalItemCount)) {

        loading = false;
        previousTotalItemCount = totalItemCount;
    }

    // If it isn’t currently loading, we check to see if we have breached
    // the visibleThreshold and need to reload more data.
    // If we do need to reload some more data, we execute onLoadMore to fetch the data.
    // threshold should reflect how many total columns there are too
    if (!loading && (lastVisibleItemPosition + visibleThreshold) > totalItemCount && dy > 0) {

        currentPage++;
        onLoadMore(currentPage, totalItemCount, view);
        loading = true;
    }
    if (!loading && (lastVisibleItemPosition + visibleThreshold) > totalItemCount) {
        currentPage++;
        onLoadMore(currentPage, totalItemCount, view);
        loading = true;
    }
}

// Call this method whenever performing new searches
public void resetState() {
    this.currentPage = this.startingPageIndex;
    this.previousTotalItemCount = 0;
    this.loading = true;
}

// Defines the process for actually loading more data based on page
protected abstract void onLoadMore(int page, int totalItemsCount, RecyclerView view);
}

以及使用它们的代码:

/*Method to generate List of data using RecyclerView with custom adapter*/
private void generateDataList(final List<Ad> photoList) {

    StaggeredGridLayoutManager staggeredGridLayoutManager = new StaggeredGridLayoutManager(2, StaggeredGridLayoutManager.VERTICAL);
    recyclerView.setLayoutManager(staggeredGridLayoutManager);

    adapter = new CustomAdapter(getActivity(), photoList);
    recyclerView.setAdapter(adapter);
    EndlessRecyclerViewScrollListener scrollListener;
    scrollListener = new EndlessRecyclerViewScrollListener(staggeredGridLayoutManager) {
        @Override
        public void onLoadMore(int page, int totalItemsCount, RecyclerView view) {
            // Triggered only when new data needs to be appended to the list
            // Add whatever code is needed to append new items to the bottom of the list
            loadNextDataFromApi(page);
        }
    };
    recyclerView.addOnScrollListener(scrollListener);

}
private void loadNextDataFromApi(int offset) {
    loadingSnackBar.show();

    Call<List<Ad>> call = service.getAllPhotosprime(offset + 1);
    Callback<List<Ad>> callback = new Callback<List<Ad>>() {
        @Override
        public void onResponse(@NonNull Call<List<Ad>> call, @NonNull Response<List<Ad>> response) {

            if (response.code() == 200) {

                loadingSnackBar.dismiss();
                adList.addAll(response.body());

                adapter.notifyItemInserted(adList.size() - 1);
                adapter.notifyDataSetChanged();

            } else {

                call.clone().enqueue(this);

            }
        }

        @Override
        public void onFailure(@NonNull Call<List<Ad>> call, @NonNull Throwable t) {
            loadingSnackBar.dismiss();
            call.clone().enqueue(this);
            Toast.makeText(getActivity(), "Something went wrong...Please try later!", Toast.LENGTH_SHORT).show();
        }
    };
    call.enqueue(callback);
}

如何在 recyclerview 的底部添加进度条,并在每次 onLoadMoreListener 调用时使其可见?我想将进度栏设置在屏幕底部的中心,而不是 recyclerview 中卡片的底部。

1 个答案:

答案 0 :(得分:0)

You can user default prograssbar by placing it on Layout file like below xml

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@color/colorback"
    app:layout_behavior="@string/appbar_scrolling_view_behavior"
    tools:showIn="@layout/activity_main">

    <android.support.v7.widget.RecyclerView
        android:id="@+id/recycleViewVideo"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_above="@id/prograssbar" />

    <ProgressBar
        android:id="@+id/prograssbar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_above="@id/adView"
        android:layout_alignParentBottom="true"
        android:layout_centerHorizontal="true"
        android:visibility="visible" />

    <LinearLayout
        android:id="@+id/adView"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:orientation="horizontal" />
</RelativeLayout>

And in main code from where you call API just handle hide/show.