SwipeRefreshLayout+RecyclerView realizes pull up refresh and pull down refresh functions

  • 2021-10-27 09:21:49
  • OfStack

SwipeRefreshLayout is a control introduced by Google for drop-down refresh, SwipeRefreshLayout has been put into sdk, and SwipeRefreshLayout has been put into support v4 after Version 19.1.

The source code is in SDK\ sdk\ extras\ android\ support\ v4\ src\ java\ android\ support\ v4\ widget\ SwipeRefreshLayout.java

Google only provides the function of drop-down refresh, and the appearance of RecyclerView is basically to replace ListView and GridView.

Today, I will talk about the most common pull-down refresh and pull-up refresh functions.

Layout file:


<android.support.v4.widget.SwipeRefreshLayout
 xmlns:android="http://schemas.android.com/apk/res/android"
 xmlns:tools="http://schemas.android.com/tools"
 android:id="@+id/swipe_refresh_widget"
 android:layout_width="match_parent"
 android:layout_height="match_parent" >
 
 <android.support.v7.widget.RecyclerView
 android:id="@android:id/list"
 android:layout_width="match_parent"
 android:layout_height="match_parent"
 android:cacheColorHint="@null"
 android:scrollbars="vertical" />
 
</android.support.v4.widget.SwipeRefreshLayout>

Reference this layout in Activity and initialize


@Override
 protected void onCreate(Bundle savedInstanceState) {
 super.onCreate(savedInstanceState);
 setContentView(R.layout.activity_main);
 
 mSwipeRefreshWidget = (SwipeRefreshLayout) findViewById(R.id.swipe_refresh_widget);
 mRecyclerView = (RecyclerView) findViewById(android.R.id.list);
 
 mSwipeRefreshWidget.setColorScheme(R.color.color1, R.color.color2,
 R.color.color3, R.color.color4);
 mSwipeRefreshWidget.setOnRefreshListener(this);
 
 //  This sentence is for, first 1 Display the loading progress bar the next time you enter the page 
 mSwipeRefreshWidget.setProgressViewOffset(false, 0, (int) TypedValue
 .applyDimension(TypedValue.COMPLEX_UNIT_DIP, 24, getResources()
 .getDisplayMetrics()));
 
 mRecyclerView.setOnScrollListener(new RecyclerView.OnScrollListener() {
 
 @Override
 public void onScrollStateChanged(RecyclerView recyclerView,
 int newState) {
 super.onScrollStateChanged(recyclerView, newState);
 if (newState == RecyclerView.SCROLL_STATE_IDLE
 && lastVisibleItem + 1 == adapter.getItemCount()) {
 mSwipeRefreshWidget.setRefreshing(true);
 //  Here, in a real project, please replace it with a network request data code. sendRequest .....
 handler.sendEmptyMessageDelayed(0, 3000);
 }
 }
 
 @Override
 public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
 super.onScrolled(recyclerView, dx, dy);
 lastVisibleItem = mLayoutManager.findLastVisibleItemPosition();
 }
 
 });
 
 mRecyclerView.setHasFixedSize(true);
 mLayoutManager = new LinearLayoutManager(this);
 mRecyclerView.setLayoutManager(mLayoutManager);
 mRecyclerView.setItemAnimator(new DefaultItemAnimator());
 
 adapter = new SampleAdapter();
 mRecyclerView.setAdapter(adapter);
 
 //  Here, in a real project, please replace it with a network request data code. sendRequest .....
 handler.sendEmptyMessageDelayed(0, 3000);
 }

Api to note in SwipeRefreshLayout:

1. setOnRefreshListener (OnRefreshListener listener) sets up drop-down listening, and when the user pulls down, it will execute callback
2. setColorSchemeColors (int... colors) sets the color change of the progress bar, and can set up to 4 colors
3. setProgressViewOffset (boolean scale, int start, int end) Adjust the distance between the progress bar and the top of the screen
4. setRefreshing (boolean refreshing) sets whether SwipeRefreshLayout is currently in a refresh state. Generally, it is set to true when requesting data, and set to false after the data is loaded into View.

Implementation of RecyclerView:

First, pull-down refresh and pull-up refresh use the progress bar of SwipeRefreshLayout


mRecyclerView = (RecyclerView) findViewById(android.R.id.list);
mRecyclerView.setOnScrollListener(new RecyclerView.OnScrollListener() {
 
 @Override
 public void onScrollStateChanged(RecyclerView recyclerView,
 int newState) {
 super.onScrollStateChanged(recyclerView, newState);
 if (newState == RecyclerView.SCROLL_STATE_IDLE
 && lastVisibleItem + 1 == adapter.getItemCount()) {
 mSwipeRefreshWidget.setRefreshing(true);
 //  Here, in a real project, please replace it with a network request data code. sendRequest .....
 handler.sendEmptyMessageDelayed(0, 3000);
 }
 }
 
 @Override
 public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
 super.onScrolled(recyclerView, dx, dy);
 lastVisibleItem = mLayoutManager.findLastVisibleItemPosition();
 }
 });
 
 mRecyclerView.setHasFixedSize(true);
 mLayoutManager = new LinearLayoutManager(this);
 mRecyclerView.setLayoutManager(mLayoutManager);
 mRecyclerView.setItemAnimator(new DefaultItemAnimator());
 
 adapter = new SampleAdapter();
 mRecyclerView.setAdapter(adapter);

In the second way, the progress bar of SwipeRefreshLayout is used to realize drop-down refresh, and the refresh prompt "loading" and other information similar to ListView is used for pull-up refresh.

We can also add an item similar to FooterView to RecyclerView.
We implemented in Adapter:


public class SampleAdapter extends RecyclerView.Adapter<ViewHolder> {
 private List<Integer> list;
 
 private static final int TYPE_ITEM = 0;
 private static final int TYPE_FOOTER = 1;
 
 public List<Integer> getList() {
 return list;
 }
 
 public SampleAdapter() {
 list = new ArrayList<Integer>();
 }
 
 // RecyclerView Adj. count Set to the total number of data + 1 ( footerView ) 
 @Override
 public int getItemCount() {
 return list.size() + 1;
 }
 
 @Override
 public int getItemViewType(int position) {
 //  Finally 1 A item Set to footerView
 if (position + 1 == getItemCount()) {
 return TYPE_FOOTER;
 } else {
 return TYPE_ITEM;
 }
 }
 
 @Override
 public void onBindViewHolder(ViewHolder holder, final int position) {
 if (holder instanceof ItemViewHolder) {
 ((ItemViewHolder) holder).textView.setText(String.valueOf(list
 .get(position)));
 }
 }
 
 @Override
 public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
 if (viewType == TYPE_ITEM) {
 View view = LayoutInflater.from(parent.getContext()).inflate(
 R.layout.list_item_text, null);
 view.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT,
 LayoutParams.WRAP_CONTENT));
 return new ItemViewHolder(view);
 }
 // type == TYPE_FOOTER  Return footerView
 else if (viewType == TYPE_FOOTER) {
 View view = LayoutInflater.from(parent.getContext()).inflate(
 R.layout.footerview, null);
 view.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT,
 LayoutParams.WRAP_CONTENT));
 return new FooterViewHolder(view);
 }
 
 return null;
 }
 
 class FooterViewHolder extends ViewHolder {
 
 public FooterViewHolder(View view) {
 super(view);
 }
 
 }
 
 class ItemViewHolder extends ViewHolder {
 TextView textView;
 
 public ItemViewHolder(View view) {
 super(view);
 textView = (TextView) view.findViewById(R.id.text);
 }
 }
}

In this way, we can do some processing for the layout of footerview, such as prompting information such as "loading," and "all loaded". More flexible by 1 point.


Related articles: