一、实现带”下拉刷新”和”加载更多”的仿ListView的RecyclerView
1、下拉刷新
方法:利用SwipeRefreshLayout来实现,将RecyclerView放在SwipeRefreshLayout中,然后调用SwipeRefreshLayout.setOnRefreshListener()方法就可以了。
布局:
<android.support.v4.widget.SwipeRefreshLayout
android:id="@+id/swip_refesh_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
>
<android.support.v7.widget.RecyclerView
android:id="@+id/recycler_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
></android.support.v7.widget.RecyclerView>
</android.support.v4.widget.SwipeRefreshLayout>
逻辑代码:
mSwipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
@Override
public void onRefresh() {
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
List<String> newDatas = new ArrayList<String>();
for (int i = 0; i < 3; i++) {
newDatas.add("new" + (i + 1));
}
//添加更新的数据,更新UI
mAdapter.addItems(newDatas);
//取消刷新动画
mSwipeRefreshLayout.setRefreshing(false);
}
}, 5000);
}
});
适配器中应有的方法:
public void addItems(List<String> newDatas) {
if (newDatas != null) {
newDatas.addAll(mDatas);
mDatas.removeAll(mDatas);
mDatas.addAll(newDatas);
notifyDataSetChanged();
}
}
SwipeRefreshLayout简介:
SwipeRefreshLayout是google官方推出的一个新的Widget,可以实现下拉刷新的效果。该控件继承自ViewGroup在support-v4包下面,不过我们升级supportlibrary的版本到19.1以上,基本使用方法:
- setOnRefreshListener(OnRefreshListener):添加下拉刷新监听器
- setRefreshing(boolean):设置是否显示刷新进度条,false-隐藏,true-显示
- isRefreshing():检测是否处于刷新状态
- setColorSchemeResources(R.color.color_red…):设置进度条的颜色,最多可以设置四种
- setProgressBackgroundColorSchemeColor(getResources().getColor(R.color.color_red)):设置进度条背景颜色
- setProgressViewOffset():设置进度条到顶部的距离等
到此,RecyclerView的下拉刷新已实现。
2、加载更多
思路:我们监听RecyclerView的滑动事件,如果滑动到最底部,则加载更多数据。
①判断该RecyclerView是否需要滚动,即子View是否超出了手机屏幕,代码如下:
private boolean isCouldLoadMore() {
//获取可以看到的子View的个数
int visibleItemCount = mRecyclerView.getChildCount();
//如果可视的子View的个数就是所有的子View,就不需要滚动
if (visibleItemCount == mAdapter.mDatas.size()) {
return false;
}
return true;
}
②在适配器中准备加载更多的动画:
public class RecyclerViewAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
public static final int PULL_TO_MORE = 0;
public static final int PULLINT_MORE = 1;
public final static int PULLED_FINISH = 2;
private final int TYPE_ITEM = 0;
private final int TYPE_FOOTER = 1;
//当前的加载状态
private int current_load_more_state = 0;
private Context mContext;
private LayoutInflater mInflater;
public List<String> mDatas;
//子view是否充满了手机屏幕
private boolean isCompleteFill = false;
public RecyclerViewAdapter(Context context, List<String> datas) {
this.mContext = context;
this.mDatas = datas;
mInflater = LayoutInflater.from(mContext);
}
@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
if (holder==null){
return;
}
if (holder instanceof ItemViewHolder){
((ItemViewHolder) holder).textView.setText(mDatas.get(position));
}
else if (holder instanceof FooterViewHolder){
String msg = "";
switch (current_load_more_state){
case PULL_TO_MORE:
msg = "上拉加载更多";
break;
case PULLINT_MORE:
msg = "正在加载...";
break;
case PULLED_FINISH:
//加载完成,初始化
current_load_more_state = 0;
msg = "上拉加载更多";
break;
default:
break;
}
((FooterViewHolder)holder).footerTextView.setText(msg);
}
}
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
//普通item的view
if (viewType == TYPE_ITEM) {
View view = mInflater.inflate(R.layout.item, parent, false);
ItemViewHolder mItemViewHolder = new ItemViewHolder(view);
return mItemViewHolder;
}
//加载更多的动画
else if (viewType == TYPE_FOOTER && isCompleteFill) {
View view = mInflater.inflate(R.layout.add_more_footer, parent, false);
FooterViewHolder mFooterViewHolder = new FooterViewHolder(view);
return mFooterViewHolder;
}
return null;
}
@Override
public int getItemCount() {
//如果已经占满了手机屏幕,就把加载更多的布局加在RecyclerView的最后面
if (isCompleteFill){
return mDatas.size()+1;
}
//否则就去掉加载更多的布局
else {
return mDatas.size();
}
}
@Override
public int getItemViewType(int position) {
//如果子View还没有占满手机屏幕,或者还没有到最后一个子View,就显示Item的布局
if (!isCompleteFill || position + 1 != getItemCount()) {
return TYPE_ITEM;
} else {
return TYPE_FOOTER;
}
}
//下拉刷新时,添加数据
public void addItems(List<String> newDatas) {
if (newDatas != null) {
newDatas.addAll(mDatas);
mDatas.removeAll(mDatas);
mDatas.addAll(newDatas);
notifyDataSetChanged();
}
}
//加载更多时,添加数据
public void addMoreDatas(List<String> moreDatas) {
if (moreDatas != null) {
mDatas.addAll(moreDatas);
current_load_more_state = PULLED_FINISH;
notifyDataSetChanged();
}
}
class ItemViewHolder extends RecyclerView.ViewHolder {
protected TextView textView;
public ItemViewHolder(View itemView) {
super(itemView);
textView = (TextView) itemView.findViewById(R.id.text_view);
}
}
class FooterViewHolder extends RecyclerView.ViewHolder {
private TextView footerTextView;
public FooterViewHolder(View itemView) {
super(itemView);
footerTextView = (TextView) itemView.findViewById(R.id.add_more_state_text);
}
}
//更改加载更多的状态
public void changeLoadMoreStatus(int status){
current_load_more_state = status;
notifyDataSetChanged();
}
//更改手机屏幕是否被占满的状态
public void changeIsCompleteFill(boolean status){
isCompleteFill = status;
notifyDataSetChanged();
}
}
③实现加载更多:
//监听滚动事件,加载更多数据
mRecyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
@Override
public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
super.onScrollStateChanged(recyclerView, newState);
if (isCouldLoadMore()) {
//子View已占满手机屏幕
mAdapter.changeIsCompleteFill(true);
//判断是否滚动到最后一个子View
if (newState == RecyclerView.SCROLL_STATE_IDLE && lastVisibleItem + 1 == mAdapter.getItemCount()) {
mAdapter.changeLoadMoreStatus(mAdapter.PULLINT_MORE);
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
List<String> moreDatas = new ArrayList<String>();
for (int i = 0; i < 3; i++) {
moreDatas.add("more data" + (i + 1));
}
mAdapter.addMoreDatas(moreDatas);
Toast.makeText(MainActivity.this, "加载完成", Toast.LENGTH_LONG).show();
}
}, 5000);
}
} else {
mAdapter.changeIsCompleteFill(false);
}
}
@Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
lastVisibleItem = mLinearLayoutManager.findLastVisibleItemPosition();
}
});
到此,RecyclerView的下拉刷新、加载更多就算实现了。
存在的问题:当子View的总高度小于手机屏幕的高度,且子View+1的总高度大于手机屏幕的高度时,加载更多的布局就会出现显示问题,暂未解决