这几天研究了下RecyclerView的使用和封装,发现还是蛮好用的,现在把学习成果分享给大家,主要是关于上拉刷新的封装
先附上效果
RecyclerView的封装如下
package com.byzk.www.recyclerviewpackage; import android.content.Context; import android.support.v7.widget.GridLayoutManager; import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.RecyclerView; import android.support.v7.widget.StaggeredGridLayoutManager; import android.util.AttributeSet; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import jp.wasabeef.recyclerview.animators.adapters.SlideInBottomAnimationAdapter; /** * Author: zhuliyuan * Time: 下午 3:26 */ public class RefreshRecyclerView extends RecyclerView { private AutoLoadAdapter autoLoadAdapter; public RefreshRecyclerView(Context context) { this(context, null); } public RefreshRecyclerView(Context context, AttributeSet attrs) { this(context, attrs, 0); } public RefreshRecyclerView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); init(); } private boolean isLoadingMore = false;//是否正在加载更多 private int loadMorePosition = -1;//记录最后刷新位置 private OnLoadDataListener loadDataListener;//加载数据监听 private boolean isLoadMoreEnable = false;//是否允许加载更多 private int footerResource;//脚布局 private void init() { setOnScrollListener(new OnScrollListener() { @Override public void onScrollStateChanged(RecyclerView recyclerView, int newState) { super.onScrollStateChanged(recyclerView, newState); int lastVisiblePosition = getLastVisiblePosition(); int itemCount = getAdapter().getItemCount(); if (lastVisiblePosition + 4 >= itemCount - 1 && !isLoadingMore && isLoadMoreEnable) { isLoadingMore = true;//设置正在刷新 loadMorePosition = itemCount - 1;//记录最后刷新位置 if (loadDataListener != null) { loadDataListener.pullUpRefresh(); } } } }); } @Override public void setAdapter(Adapter adapter) { autoLoadAdapter = new AutoLoadAdapter(new SlideInBottomAnimationAdapter(adapter));//添加动画 super.setAdapter(autoLoadAdapter); } /** * 设置是否允许加载更多 * * @param isEnable */ public void setLoadMoreEnable(boolean isEnable) { this.isLoadMoreEnable = isEnable; } /** * 设置脚布局 */ public void setFooterResource(int footerResource) { this.footerResource = footerResource; } /** * 加载完成 * */ private void loadMoreComplete() { this.isLoadingMore = false; } /** * 获得最后一条可见 * * @return */ private int getLastVisiblePosition() { LayoutManager layoutManager = getLayoutManager(); int position = -1; if (layoutManager instanceof LinearLayoutManager) { position = ((LinearLayoutManager) layoutManager).findLastVisibleItemPosition(); } else if (layoutManager instanceof GridLayoutManager) { position = ((GridLayoutManager) layoutManager).findLastVisibleItemPosition(); } else if (layoutManager instanceof StaggeredGridLayoutManager) { int[] positions = ((StaggeredGridLayoutManager) layoutManager).findLastVisibleItemPositions(null);//返回最后可见的一行position for (int i = 0; i < positions.length - 1; i++) { position = Math.max(positions[i], positions[i + 1]); } } return position; } /** * 上拉刷新回调 * * @param listener */ public void setOnLoadDataListener(OnLoadDataListener listener) { this.loadDataListener = listener; } public interface OnLoadDataListener { void pullUpRefresh();//上拉刷新 } /** * 刷新更多数据 */ public void notifyMoreData() { getAdapter().notifyItemRemoved(loadMorePosition); loadMoreComplete(); } /** * 刷新最新数据 */ public void notifyNewData(){ getAdapter().notifyDataSetChanged(); } public class AutoLoadAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> { private Adapter dataAdapter;//数据adapter private final int TYPE_NORMAL = 0;//正常 private final int TYPE_FOOTER = 1;//底部布局 public AutoLoadAdapter(RecyclerView.Adapter adapter) { this.dataAdapter = adapter; } @Override public int getItemViewType(int position) { if (position == getItemCount() - 1 && isLoadMoreEnable) { return TYPE_FOOTER; } return TYPE_NORMAL; } @Override public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { ViewHolder holder = null; if (viewType == TYPE_FOOTER) {//脚部 holder = new FooterViewHolder(LayoutInflater.from(parent.getContext()).inflate(footerResource, parent, false)); } else if (viewType == TYPE_NORMAL) {//数据 holder = dataAdapter.onCreateViewHolder(parent, viewType); } return holder; } @Override public void onBindViewHolder(ViewHolder holder, int position) { int itemViewType = getItemViewType(position); if (itemViewType != TYPE_FOOTER) { dataAdapter.onBindViewHolder(holder, position); } } @Override public int getItemCount() { if (dataAdapter.getItemCount() != 0) { int count = dataAdapter.getItemCount(); if (isLoadMoreEnable)//增加了脚布局 count++; return count; } return 0; } public class FooterViewHolder extends RecyclerView.ViewHolder { public FooterViewHolder(View itemView) { super(itemView); } } } }
提供数据Adapter如下
package com.byzk.www.recyclerviewpackage; import android.support.v7.widget.RecyclerView; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.TextView; import java.util.List; /** * Author: zhuliyuan * Time: 下午 5:36 */ public class MyAdapter extends RecyclerView.Adapter<MyAdapter.MyViewHolder> { private List<String> dataList; @Override public MyAdapter.MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { MyViewHolder myViewHolder = new MyViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.item_layout, parent, false)); return myViewHolder; } @Override public void onBindViewHolder(MyAdapter.MyViewHolder holder, int position) { holder.tv.setText(dataList.get(position)); } public class MyViewHolder extends RecyclerView.ViewHolder{ private TextView tv; public MyViewHolder(View itemView) { super(itemView); tv = (TextView) itemView.findViewById(R.id.tv); } } @Override public int getItemCount() { return (dataList == null || dataList.size() == 0)?0:dataList.size(); } public void setData(List<String> dataList){ this.dataList = dataList; } }
item布局如下
<?xml version="1.0" encoding="utf-8"?> <android.support.v7.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android" xmlns:card_view="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="60dp" android:layout_marginLeft="5dp" android:layout_marginRight="5dp" android:clickable="true" android:foreground="?attr/selectableItemBackground" card_view:cardBackgroundColor="#0094ff" card_view:cardCornerRadius="6dp" card_view:cardElevation="5dp"> <TextView android:id="@+id/tv" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center" android:text="哈哈哈" android:textColor="#000" /> </android.support.v7.widget.CardView>
activity中代码如下
package com.byzk.www.recyclerviewpackage; 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.DefaultItemAnimator; import android.support.v7.widget.LinearLayoutManager; import java.util.ArrayList; import java.util.List; import jp.wasabeef.recyclerview.animators.adapters.AlphaInAnimationAdapter; import jp.wasabeef.recyclerview.animators.adapters.ScaleInAnimationAdapter; import jp.wasabeef.recyclerview.animators.adapters.SlideInBottomAnimationAdapter; public class MainActivity extends AppCompatActivity { private List<String> dataList = new ArrayList<>(); private RefreshRecyclerView rv; private MyAdapter myAdapter; private SwipeRefreshLayout srl; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); init(); } private void init() { initView(); initData(); initListener(); } private void initView() { srl = (SwipeRefreshLayout) findViewById(R.id.srl); srl.setColorSchemeResources(android.R.color.holo_red_light, android.R.color.holo_blue_light, android.R.color.holo_green_light); rv = (RefreshRecyclerView) findViewById(R.id.rv); rv.setLayoutManager(new LinearLayoutManager(this)); rv.setItemAnimator(new DefaultItemAnimator()); rv.setLoadMoreEnable(true); rv.setFooterResource(R.layout.item_footer); myAdapter = new MyAdapter(); rv.setAdapter(myAdapter); } private void initData() { for (int i = 0; i < 20; i++) { dataList.add("数据" + i); } myAdapter.setData(dataList); rv.notifyNewData(); } private void initListener() { rv.setOnLoadDataListener(new RefreshRecyclerView.OnLoadDataListener() { @Override public void pullUpRefresh() { handler.postDelayed(new Runnable() { @Override public void run() { for (int i = 0; i < 10; i++) { dataList.add("更多数据" + i); } myAdapter.setData(dataList);//设置新数据 rv.notifyMoreData();//刷新数据 } }, 2000); } }); srl.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() { @Override public void onRefresh() { handler.postDelayed(new Runnable() { @Override public void run() { srl.setRefreshing(false); dataList.add(0, "最新数据"); myAdapter.setData(dataList);//设置新数据 rv.notifyNewData();//刷新数据 } }, 2000); } }); } private Handler handler = new Handler(); }
下拉刷新用的是v4包中的SwipeRefreshLayout直接包裹在自己封装的RecyclerView的外层,上拉加载更多用的是自己封装的RecyclerView.
接下来是activity中的布局文件
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context="com.byzk.www.recyclerviewpackage.MainActivity"> <android.support.v4.widget.SwipeRefreshLayout android:id="@+id/srl" android:layout_width="wrap_content" android:layout_height="wrap_content"> <com.byzk.www.recyclerviewpackage.RefreshRecyclerView android:id="@+id/rv" android:layout_width="match_parent" android:layout_height="wrap_content" /> </android.support.v4.widget.SwipeRefreshLayout> </RelativeLayout>
源码传送门
例子中recyclerview动画地址https://github.com/wasabeef/recyclerview-animators
如果有什么写的不好的地方希望大家指出,互相讨论学习,谢谢!