软件编程
位置:首页>> 软件编程>> Android编程>> Android RecyclerView自定义上拉和下拉刷新效果

Android RecyclerView自定义上拉和下拉刷新效果

作者:tijjyire  发布时间:2022-03-17 23:06:00 

标签:RecyclerView,上拉刷新,下拉刷新

使用RecyclerView越来越多了,基本可以不用listview了,但是这个新的控件谷歌官方似乎设计的没有想listview那样方便快捷,listview自带有headview和 footerview所有我们很方便的可以实现上拉,下拉刷新,但是我们使用recyclerview就没有那样的舒服了,需要自己动手来实现这两个模块了。

本人参考了其他几篇博客使用了下感觉都有bug存在,于是自己改进了下,基本实现了功能,由于时间原因代码封装的还不彻底,仅供参考。

首页布局:activity_notice


<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
 xmlns:app="http://schemas.android.com/apk/res-auto"
 android:layout_width="match_parent"
 android:layout_height="match_parent"
 android:background="@android:color/white"
 android:orientation="vertical"
 >

<include layout="@layout/toolbar" />

<android.support.v4.widget.SwipeRefreshLayout
   android:id="@+id/SwipeRefreshLayout"
   android:layout_width="match_parent"
   android:layout_height="match_parent"
   app:layout_behavior="@string/appbar_scrolling_view_behavior">

<android.support.v7.widget.RecyclerView
     android:id="@+id/recyclerView"
     android:layout_width="match_parent"
     android:layout_height="match_parent"
     android:scrollbars="vertical"></android.support.v7.widget.RecyclerView>
 </android.support.v4.widget.SwipeRefreshLayout>
</android.support.design.widget.CoordinatorLayout>  

子item布局:item_base


<?xml version="1.0" encoding="utf-8"?>

<android.support.v7.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
 xmlns:app="http://schemas.android.com/apk/res-auto"
 android:layout_width="match_parent"
 android:layout_height="wrap_content"
 android:layout_marginLeft="@dimen/margin_10"
 android:layout_marginRight="@dimen/margin_10"
 android:layout_marginTop="6dp"
 android:orientation="vertical"
 app:cardBackgroundColor="@color/line"
 app:cardPreventCornerOverlap="true"
 app:cardUseCompatPadding="true"
 app:contentPadding="6dp">

<LinearLayout
   android:layout_width="match_parent"
   android:layout_height="match_parent"
   android:orientation="vertical">

<TextView
     android:id="@+id/tv_date"
     style="@style/NormalTextView"
     android:layout_width="wrap_content"
     android:layout_height="wrap_content"
     android:text="2016-10-9 10:00" />

<android.support.v7.widget.CardView
     android:layout_width="match_parent"
     android:layout_height="match_parent"
     android:orientation="vertical"
     app:cardBackgroundColor="@color/white"
     app:cardPreventCornerOverlap="true"
     app:cardUseCompatPadding="true"
     app:contentPadding="10dp">

<TextView
       android:id="@+id/tv_title"
       style="@style/SmallGreyTextView"
       android:layout_width="wrap_content"
       android:layout_height="wrap_content"
       android:ellipsize="end"
       android:maxLines="2"
       android:text="。。。,看到这个场景。我看着她她看着我,说道:“怎么样,我当年的手工还不错吧。。。。。。。。。”" />

</android.support.v7.widget.CardView>
 </LinearLayout>

</android.support.v7.widget.CardView>

脚布局 item_foot


<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
 xmlns:tools="http://schemas.android.com/tools"
 android:layout_width="match_parent"
 android:layout_height="40dp"
 android:gravity="center"
 android:orientation="horizontal"
 android:id="@+id/ll"
>

<ProgressBar
   android:layout_marginRight="6dp"
   android:id="@+id/progressBar"
   style="?android:attr/progressBarStyleSmall"
   android:layout_width="wrap_content"
   android:layout_height="wrap_content"
   android:layout_gravity="center" />

<TextView
   android:id="@+id/tv"
   style="@style/SmallGreyTextView"
   android:layout_width="wrap_content"
   android:layout_height="wrap_content"
   android:layout_gravity="center"
   android:text="@string/loading" />

</LinearLayout>

toolbar


<?xml version="1.0" encoding="utf-8"?>
<merge xmlns:android="http://schemas.android.com/apk/res/android"
 xmlns:app="http://schemas.android.com/apk/res-auto">

<android.support.design.widget.AppBarLayout
   android:layout_width="match_parent"
   android:layout_height="wrap_content"
   android:fitsSystemWindows="true">

<android.support.v7.widget.Toolbar
     android:id="@+id/toolbar"
     android:layout_width="match_parent"
     android:layout_height="wrap_content"
     android:background="@color/blueStatus"
     android:minHeight="?attr/actionBarSize"
     app:layout_scrollFlags="scroll|enterAlways"
     app:navigationIcon="?attr/homeAsUpIndicator"
     app:theme="@style/Theme.AppCompat.NoActionBar">

</android.support.v7.widget.Toolbar>
 </android.support.design.widget.AppBarLayout>

首页 MainActivity


package com.lxl.refresh;

import android.os.Bundle;
import android.os.Handler;
import android.support.v4.widget.SwipeRefreshLayout;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.Toolbar;
import android.util.Log;
import android.view.View;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import butterknife.ButterKnife;
import butterknife.InjectView;

/**
* Description:
* Author:lxl
* Date: 2016/10/9 10:15
*/
public class MainActivity extends AppCompatActivity {

@InjectView(R.id.toolbar)
 Toolbar toolbar;
 @InjectView(R.id.recyclerView)
 RecyclerView recyclerView;
 @InjectView(R.id.SwipeRefreshLayout)
 SwipeRefreshLayout swipeRefreshLayout;
 boolean isSlidingToLast = false; //判断滚动状态
 boolean isLoading;
 private List<Map<String, Object>> data = new ArrayList<>();
 private RecyclerViewAdapter adapter = new RecyclerViewAdapter(this, data);
 private Handler handler = new Handler();

@Override
 public void onCreate(Bundle savedInstanceState) {
   super.onCreate(savedInstanceState);
   setContentView(R.layout.activity_notice);
   ButterKnife.inject(this);
   initView();
   Map<String, Object> map = new HashMap<>();
   initData();
 }

public void initView() {
   setSupportActionBar(toolbar);
   toolbar.setTitle(R.string.notice);
   toolbar.setNavigationOnClickListener(new View.OnClickListener() {
     @Override
     public void onClick(View v) {
       finish();
     }
   });

swipeRefreshLayout.setColorSchemeResources(R.color.blueStatus);
   swipeRefreshLayout.post(new Runnable() {
     @Override
     public void run() {
       swipeRefreshLayout.setRefreshing(true);
     }
   });

swipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
     @Override
     public void onRefresh() {
       handler.postDelayed(new Runnable() {
         @Override
         public void run() {
           data.clear();
           getData();
         }
       }, 2000);
     }
   });
   final LinearLayoutManager layoutManager = new LinearLayoutManager(this);
   recyclerView.setLayoutManager(layoutManager);
   recyclerView.setAdapter(adapter);
   recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {

@Override
     public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
       super.onScrollStateChanged(recyclerView, newState);
       Log.d("test", "StateChanged = " + newState); //滑动状态改变时触发有0,1,2三种状态

}

@Override
     public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
       super.onScrolled(recyclerView, dx, dy);
       if (dy > 0) {
         //大于0表示正在向下滚动
         isSlidingToLast = true;
       } else {
         //小于等于0表示停止或向上滚动
         isSlidingToLast = false;
       }
       Log.d("test", "onScrolled"); //当RecyclerView滑动时触发类似点击事件的MotionEvent.ACTION_MOVE
       int lastVisibleItemPosition = layoutManager.findLastVisibleItemPosition();
       if (lastVisibleItemPosition + 1 == adapter.getItemCount()&& isSlidingToLast) {
         Log.d("test", "loading executed");//当且仅当滑动到最后一项并且手指上拉抛出时才执行

boolean isRefreshing = swipeRefreshLayout.isRefreshing();
         Log.d("test", "hahh"+isRefreshing);
         if (isRefreshing) { //如何在下拉刷新则隐藏脚布局并且返回
           adapter.notifyItemRemoved(adapter.getItemCount());
           return;
         }
         if (!isLoading) {
           isLoading = true;
           handler.postDelayed(new Runnable() {
             @Override
             public void run() {
               getData(); //延时执行加载
               Log.d("test", "load more completed");
               isLoading = false;
             }
           }, 1000);
         }
       }
     }
   });

//添加点击事件
   adapter.setOnItemClickListener(new RecyclerViewAdapter.OnItemClickListener() {
     @Override
     public void onItemClick(View view, int position) {
       Log.d("test", "item position = " + position);
     }

@Override
     public void onItemLongClick(View view, int position) {

}
   });
 }

public void initData() { //第一次进来的时候加载数据
   handler.postDelayed(new Runnable() {
     @Override
     public void run() {
       getData();
     }
   }, 1500);

}

/**
  * 获取测试数据
  */
 private void getData() {
   for (int i = 0; i < 6; i++) { //每次加载六条数据
     Map<String, Object> map = new HashMap<>();
     data.add(map);
   }
   adapter.notifyDataSetChanged();
   swipeRefreshLayout.setRefreshing(false); //加载数据后收起下拉刷新
   Log.d("test", adapter.getItemCount()+"");

//    adapter.notifyItemRemoved(adapter.getItemCount()); //加载数据后上拉刷新的脚布局移除掉

//    adapter.footerHolder.ll.setVisibility(View.GONE);
   //加载数据后上拉刷新的脚布局隐藏掉
   adapter.setmCreateViewHolder(new RecyclerViewAdapter.onHolderCreate() {
     @Override
     public void created() {
       if (isSlidingToLast==false){
         adapter.footerHolder.ll.setVisibility(View.GONE);
       }else{
         adapter.footerHolder.ll.setVisibility(View.VISIBLE);
       }
     }
   });
 }

}

在第106行中通过这三个条件判断就可以下拉刷新的执行。
RecyclerView的适配器:RecyclerViewAdapter


package com.lxl.refresh;

import android.content.Context;
import android.support.v7.widget.RecyclerView.Adapter;
import android.support.v7.widget.RecyclerView.ViewHolder;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.LinearLayout;
import android.widget.ProgressBar;
import android.widget.TextView;

import java.util.List;

public class RecyclerViewAdapter extends Adapter<ViewHolder> {

private static final int TYPE_ITEM = 0;
 private static final int TYPE_FOOTER = 1;
 private Context context;
 private List data;

protected FootViewHolder footerHolder;

public RecyclerViewAdapter(Context context, List data) {
   this.context = context;
   this.data = data;
 }
 //-------------------------------------
 public interface onHolderCreate{ //定义一个viewholder回调接口
   void created();
 }

public onHolderCreate getmCreateViewHolder() {
   return mCreateViewHolder;
 }

public void setmCreateViewHolder(onHolderCreate mCreateViewHolder) {
   this.mCreateViewHolder = mCreateViewHolder;
 }

private onHolderCreate mCreateViewHolder;

//-------------------------------------

public interface OnItemClickListener {
   void onItemClick(View view, int position);

void onItemLongClick(View view, int position);
 }

private OnItemClickListener onItemClickListener;

public void setOnItemClickListener(OnItemClickListener onItemClickListener) {
   this.onItemClickListener = onItemClickListener;
 }

@Override
 public int getItemCount() {
   return data.size() == 0 ? 0 : data.size() + 1; //添加脚布局
 }

@Override
 public int getItemViewType(int position) {
   if (position + 1 == getItemCount()) {
     return TYPE_FOOTER; //脚布局
   } else {
     return TYPE_ITEM; //普通item
   }
 }

@Override
 public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
   if (viewType == TYPE_ITEM) { //创建普通类型的item布局
     View view = LayoutInflater.from(context).inflate(R.layout.item_base, parent,
         false);
     Log.d("test", "创建普通类型的item布局");
     return new ItemViewHolder(view);
   } else if (viewType == TYPE_FOOTER) { //创建脚布局类型的item布局
     View view = LayoutInflater.from(context).inflate(R.layout.item_foot, parent,
         false);
     footerHolder=new FootViewHolder(view);
     Log.d("test", "创建脚布局类型的item布局");

return footerHolder;
   }
   return null;
 }

@Override
 public void onBindViewHolder(final ViewHolder holder, int position) {
   //在onCreateViewHolder执行完成后回调
   if (holder instanceof FootViewHolder){
     if (mCreateViewHolder!=null){
       mCreateViewHolder.created();
     }
   }
   if (holder instanceof ItemViewHolder) {
     //holder.tv.setText(data.get(position));
     if (onItemClickListener != null) {
       holder.itemView.setOnClickListener(new View.OnClickListener() {
         @Override
         public void onClick(View v) {
           int position = holder.getLayoutPosition();
           onItemClickListener.onItemClick(holder.itemView, position);
         }
       });

holder.itemView.setOnLongClickListener(new View.OnLongClickListener() {
         @Override
         public boolean onLongClick(View v) {
           int position = holder.getLayoutPosition();
           onItemClickListener.onItemLongClick(holder.itemView, position);
           return false;
         }
       });
     }
   }
 }

static class ItemViewHolder extends ViewHolder {

TextView tv;

public ItemViewHolder(View view) {
     super(view);
     tv = (TextView) view.findViewById(R.id.tv_date);
   }
 }

class FootViewHolder extends ViewHolder {
    LinearLayout ll;
    ProgressBar pb;
    TextView tv;
   public FootViewHolder(View view) {
     super(view);
     ll=(LinearLayout) view.findViewById(R.id.ll);
     pb=(ProgressBar) view.findViewById(R.id.progressBar);
     tv=(TextView) view.findViewById(R.id.tv);
   }
 }
}

在第30行定义一个借口用来通知下拉刷新后隐藏脚布局,主要在onCreateViewHolder执行完成后回调。

看看效果图

Android RecyclerView自定义上拉和下拉刷新效果

0
投稿

猜你喜欢

手机版 软件编程 asp之家 www.aspxhome.com