android提供了下拉刷新控件SwipeRefreshLayout正卧,并沒(méi)有提供上拉加載控件缭贡,Recyclerview又并不像Listview一樣提供addHead,addFoot接口,只能通過(guò)自定義實(shí)現(xiàn)向挖。本文實(shí)現(xiàn)了Item相同時(shí)recyclerview的上拉加載功能蚕甥。
首先定義一個(gè)基類adapter哪替,代碼里注釋寫的很清楚了
public abstract class BaseRecycleAdapter<T> extends RecyclerView.Adapter<BaseRecycleAdapter.BaseHolder> {
public List<T> mDatas;
private final Context mContext;
private static final int TYPE_ITEM = 0; //普通Item View
private static final int TYPE_FOOTER = 1; //底部FootView
public static final int PULL_UP_LOAD_MORE = 0; //上拉加載
public static final int LOADING_MORE = 1; //正在加載中
public static final int NO_MORE_DATA = 2; //加載完成沒(méi)有數(shù)據(jù)
private int load_more_status = 0; //上拉加載狀態(tài)默認(rèn)0
private OnItemClickListener onItemClickListener;
public BaseRecycleAdapter(Context context) {
mContext = context;
}
/**
* 設(shè)置數(shù)據(jù)源 泛型T代表list的泛型
* @param datas
*/
public void setData(List<T> datas) {
mDatas = datas;
}
/**
* item點(diǎn)擊事件
* @param onItemClickListener
*/
public void setOnItemClickListener(OnItemClickListener onItemClickListener){
this.onItemClickListener = onItemClickListener;
}
/**
* 根據(jù)不同的viewType創(chuàng)建不同的holder
* @param parent
* @param viewType
* @return
*/
@Override
public BaseHolder onCreateViewHolder(ViewGroup parent, int viewType) {
BaseHolder holder = null;
View view = null;
if (viewType == TYPE_ITEM) {
view = LayoutInflater.from(mContext).inflate(getLayoutId(viewType), parent, false);
} else {
view = LayoutInflater.from(mContext).inflate(R.layout.pull_load_more, parent, false);
}
holder = new BaseHolder(view);
return holder;
}
@Override
public void onBindViewHolder(BaseHolder holder, final int position) {
//底部Item 根據(jù)傳入的狀態(tài)更改布局(load_more_status)
if (holder.getItemViewType() == BaseRecycleAdapter.TYPE_FOOTER) {
ProgressBar progressBar = (ProgressBar) holder.getView(R.id.progressBar);
TextView tv_progress_text = (TextView) holder.getView(R.id.tv_progress_text);
switch (load_more_status){
case LOADING_MORE:
tv_progress_text.setText("正在加載數(shù)據(jù)");
progressBar.setVisibility(View.VISIBLE);
break;
case PULL_UP_LOAD_MORE:
if (getItemCount()<10){
progressBar.setVisibility(View.INVISIBLE);
tv_progress_text.setText("");
}else {
tv_progress_text.setText("上拉加載更多");
progressBar.setVisibility(View.INVISIBLE);
}
break;
case NO_MORE_DATA:
tv_progress_text.setText("沒(méi)有更多數(shù)據(jù)了");
progressBar.setVisibility(View.INVISIBLE);
break;
}
}
//普通Item 綁定數(shù)據(jù)
if (holder.getItemViewType() == BaseRecycleAdapter.TYPE_ITEM) {
onBindData(holder, position, mDatas);
holder.itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (onItemClickListener!=null){
onItemClickListener.onItemClick(position,v);
}
}
});
}
}
/**
* 獲取item數(shù)量
* @return
*/
@Override
public int getItemCount() {
return mDatas == null ? 0 : mDatas.size() + 1;
}
/**
* 獲取item類型(普通item 、底部item)
* @param position
* @return
*/
@Override
public int getItemViewType(int position) {
if (mDatas == null)
return TYPE_ITEM;
if (position + 1 == getItemCount()) {
return TYPE_FOOTER;
} else {
return TYPE_ITEM;
}
}
/**
* 根據(jù)傳入status改變foot狀態(tài)并刷新數(shù)據(jù)
* @param status
*/
public void changeMoreStatus(int status) {
load_more_status = status;
notifyDataSetChanged();
}
/**
* 根據(jù)type 返回不同的布局
*
* @param type
* @return
*/
public abstract int getLayoutId(int type);
/**
* 綁定數(shù)據(jù)(做成抽象 在子類實(shí)現(xiàn))
* @param holder
* @param position
* @param mDataList
*/
public abstract void onBindData(BaseHolder holder, int position, List<T> mDataList);
public static class BaseHolder extends RecyclerView.ViewHolder {
private Map<Integer, View> mViewMap;
public View mView;
public BaseHolder(View itemView) {
super(itemView);
mView = itemView;
mViewMap = new HashMap<>();
}
public View getView(int id) {
View view = mViewMap.get(id);
if (view == null) {
view = mView.findViewById(id);
mViewMap.put(id, view);
}
return view;
}
}
}
自定義Recyclerview
package com.wckj.myrecyclerview;
import android.content.Context;
import android.support.annotation.Nullable;
import android.support.v7.widget.GridLayoutManager;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.util.AttributeSet;
import com.wckj.myrecyclerview.Test.BaseRecycleAdapter;
/**
* Created by HQL
* on 2018/5/21 0021.
*/
public class MyRecyclerView extends RecyclerView {
private BaseRecycleAdapter myLoadMoreAdapter;
OnloadListener mOnLoadListener = null;
private boolean haveData = true;
public MyRecyclerView(Context context) {
this(context,null);
}
public MyRecyclerView(Context context, @Nullable AttributeSet attrs) {
this(context, attrs,0);
}
public MyRecyclerView(Context context, @Nullable AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
setOnScrollListener(null);
}
@Override
public void setOnScrollListener(OnScrollListener listener) {
LoadMoreDataListener loadMoreListener = new LoadMoreDataListener(listener);
super.setOnScrollListener(loadMoreListener);
}
@Override
public void setAdapter(Adapter adapter) {
if (!( adapter instanceof BaseRecycleAdapter)){
return;
}
myLoadMoreAdapter = (BaseRecycleAdapter) adapter;
super.setAdapter(myLoadMoreAdapter);
}
//自定義的接口方便回調(diào)
public void setOnLoadListener(OnloadListener listener) {
mOnLoadListener = listener;
}
//重寫OnScrollListener
class LoadMoreDataListener extends OnScrollListener{
private OnScrollListener listener;
private int lastVisibleItem;
public LoadMoreDataListener(OnScrollListener listener) {
this.listener = listener;
}
/**
* 當(dāng)目前顯示是最后一個(gè)條目的時(shí)候
* @param recyclerView
* @param newState
*/
@Override
public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
//當(dāng)目前顯示是最后一個(gè)條目的時(shí)候繼續(xù)向下執(zhí)行
if (newState == RecyclerView.SCROLL_STATE_IDLE &&lastVisibleItem + 1 == getAdapter().getItemCount()){
if (mOnLoadListener != null && haveData) {
//改變底部foot狀態(tài)
myLoadMoreAdapter.changeMoreStatus(BaseRecycleAdapter.LOADING_MORE);
//通過(guò)接口回調(diào)回去
mOnLoadListener.OnLoadData();
}
}
if (listener != null) {
listener.onScrollStateChanged(recyclerView, newState);
}
}
/**
* 計(jì)算最后一個(gè)可見(jiàn)條目(lastVisibleItem)
* 目前只支持 LinearLayoutManager和GridLayoutManager兩種類型
* @param recyclerView
* @param dx
* @param dy
*/
@Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
if (getLayoutManager() instanceof LinearLayoutManager) {
LinearLayoutManager lm = (LinearLayoutManager) getLayoutManager();
lastVisibleItem = lm.findLastVisibleItemPosition();
} else if (getLayoutManager() instanceof GridLayoutManager) {
GridLayoutManager gm = (GridLayoutManager) getLayoutManager();
lastVisibleItem = gm.findLastVisibleItemPosition();
}
if (listener != null) {
listener.onScrolled(recyclerView, dx, dy);
}
}
}
/**
* 數(shù)據(jù)加載完成后調(diào)用
* @param haveData
*/
public void loadComplete(final boolean haveData) {
//判斷時(shí)候還有數(shù)據(jù)
this.haveData = haveData;
//改變底部foot狀態(tài)
if (!haveData) {
myLoadMoreAdapter.changeMoreStatus(BaseRecycleAdapter.NO_MORE_DATA);
} else {
myLoadMoreAdapter.changeMoreStatus(BaseRecycleAdapter.PULL_UP_LOAD_MORE);
}
}
}
在布局文件使用
<?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="match_parent"
tools:context="com.wckj.myrecyclerview.MainActivity">
<com.wckj.myrecyclerview.MyRecyclerView
android:id="@+id/my_recyclerview"
android:layout_width="match_parent"
android:layout_height="match_parent">
</com.wckj.myrecyclerview.MyRecyclerView>
</LinearLayout>
需要用到的接口
interface OnloadListener {
void OnLoadData();
}
通過(guò)自定義的adapter繼承上面的BaseRecycleAdapter
package com.wckj.myrecyclerview.Test;
import android.content.Context;
import android.widget.TextView;
import com.wckj.myrecyclerview.R;
import java.util.List;
/**
* Created by HQL
* on 2018/5/22 0022.
*/
public class MyRecyViewAdapter extends BaseRecycleAdapter<String> {
public MyRecyViewAdapter(Context context) {
super(context);
}
@Override
public int getLayoutId(int type) {
return R.layout.normal_item;
}
@Override
public void onBindData(BaseHolder holder, int position, List<String> data) {
TextView view = (TextView) holder.getView(R.id.tv_normal_item);
view.setText(data.get(position));
}
}
在Activity中使用
package com.wckj.myrecyclerview;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.LinearLayoutManager;
import android.view.View;
import com.wckj.myrecyclerview.Test.MyRecyViewAdapter;
import java.util.ArrayList;
public class MainActivity extends AppCompatActivity implements OnItemClickListener {
private MyRecyclerView myRecyclerView;
private ArrayList<String> data = new ArrayList<>();
private int j = 1;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initData();
myRecyclerView = (MyRecyclerView) findViewById(R.id.my_recyclerview);
myRecyclerView.setLayoutManager(new LinearLayoutManager(this,LinearLayoutManager.VERTICAL,false));
MyRecyViewAdapter adapter = new MyRecyViewAdapter(this);
adapter.setData(data);
adapter.setOnItemClickListener(this);
myRecyclerView.setAdapter(adapter);
myRecyclerView.setOnLoadListener(new OnloadListener() {
@Override
public void OnLoadData() {
if (j==5) {
//數(shù)據(jù)加載完成調(diào)用loadComplete菇怀,改變foot狀態(tài)
myRecyclerView.loadComplete(false);
return;
}
initData();
}
});
}
private void initData() {
j++;
for (int i=0;i<20;i++){
data.add("我是一個(gè)粉刷匠凭舶,代號(hào)"+i);
}
}
@Override
public void onItemClick(int position, View view) {
}
}
基本上就是這些,稍后代碼會(huì)上傳github有需要可以自行下載