RecyclerView+SwipeRefreshLayout两个控件同时使用

时间:2021-09-30 18:08:30

RecyclerView+SwipeRefreshLayout


Google给我提供了一个很好的控件来取代listview。今天特意去弄了一下,因为这段时间忙,上次遗留下一个问题还没有解决,这些天是寝食不安啊。所以趁着今天有点空,所以就抽空重新看了下那个问题,终于解决了。(我这里遇到的问题是,RecyclerView数据错乱的问题)


这里喔顺便也把Google提供的自动刷新的控件也讲了,这个控件不难,但是很实用。我们在很多的app里面已经用上这个控件了。所以我们要跟上时代的步伐。


先上效果图:

RecyclerView 

RecyclerView+SwipeRefreshLayout两个控件同时使用


SwipeRefreshLayout

RecyclerView+SwipeRefreshLayout两个控件同时使用



具体的说明已经在代码中进行说明了,请认真查看代码注释



布局文件是这样的:


<span style="font-size:18px;"><?xml version="1.0" encoding="utf-8"?>
<!--这里用到的是v4包,里面包含了SwipeRefreshLayout,直接引用就OK了-->
<android.support.v4.widget.SwipeRefreshLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/refreshLayout"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior"
tools:context="com.kuyu.recycleview.MainActivity"
tools:showIn="@layout/app_bar_main">

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

<TextView
android:id="@+id/tv_refreshing"
android:layout_width="match_parent"
android:gravity="center"
android:textColor="#f3d468"
android:textSize="20sp"
android:visibility="invisible"
android:layout_height="wrap_content"
android:text="正在刷新中,请稍等..." />

<!--这里用到的是v7包,里面包含了RecyclerView,直接引用就OK了-->
<android.support.v7.widget.RecyclerView
android:id="@+id/recycleView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="@+id/tv_refreshing" />
</RelativeLayout>

</android.support.v4.widget.SwipeRefreshLayout>
</span>



RecycleView:
   适配器

package com.kuyu.recycleview.adapter;

import android.app.Activity;
import android.support.v7.widget.RecyclerView;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;

import com.kuyu.recycleview.R;

import java.util.List;

/**
* Created by tanksu.yaojt on 16/4/30.
* <p/>
* 这里要着重说明一下
* <p/>
* 我的问题就是在这里:原先是利用自己生成的ViewHolder 在onBindViewHolder()方法里面进行设置数据
* 然后的话,那个ViewHolder是一直没有按照正常对应的位置进行显示,就造成错误
* <p/>
* 然后解决问题的方法是:我们要继承RecyclerView.Adapter<RecycleViewAdapter.MyViewHolder>
* 然后把我们自定义的ViewHolder 放到里面去,然后RecyclerView 就会用你传入的类来作为参数进行传递
* 然后我们可以看到在public void onBindViewHolder(MyViewHolder holder, int position)
* 回调里面,传的参数就是我们自定义的ViewHolder了。然后我们就可以对回传回来的 holder 进行数据设置了
* 问题解决。
*/
public class RecycleViewAdapter extends RecyclerView.Adapter<RecycleViewAdapter.MyViewHolder> {

private Activity mActivity;
private List<String> mList;
private MyViewHolder myViewHolder;

/**
* 构造函数,传入一个数据源
*
* @param activity activity
* @param list list
*/
public RecycleViewAdapter(Activity activity, List<String> list) {
this.mActivity = activity;
this.mList = list;
}

/**
* 这里是创建一个ViewHolder
*
* @param parent parent
* @param viewType viewType
* @return myViewHolder
*/
@Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = mActivity.getLayoutInflater().inflate(R.layout.recycleview_item, parent, false);
myViewHolder = new MyViewHolder(view);
return myViewHolder;
}

/**
* 这里进行数据绑定,就是将数据放入到对应的item布局中。
* 我在这里进行了打印,发现滚动的时候,这里一直会调用
* 但是onCreateViewHolder 就不再调用了
* 据我的理解就是onCreateViewHolder在创建好了当前屏幕可以显示的item条数 + 1 之后,
* 再上下滚动,就是利用回收的view了,所以不用在创建ViewHolder了
*
* @param holder holder
* @param position position
*/
@Override
public void onBindViewHolder(MyViewHolder holder, int position) {
//这是我一开始设置数据的方法,直接调用的是onCreateViewHolder()方法创建好的那个vh
//事实证明是不可以的,造成数据错乱
// myViewHolder.tv_itemShow.setText(mList.get(position));
holder.tv_itemShow.setText(mList.get(position));
}

/**
* 得到数据源的总条数
*
* @return size()
*/
@Override
public int getItemCount() {
return mList.size();
}

/**
* 自定义的MyViewHolder 继承自RecyclerView.ViewHolder
* 记住一定要继承自RecyclerView.ViewHolder
*/
class MyViewHolder extends RecyclerView.ViewHolder {
TextView tv_itemShow;//这里我只是弄了一个tv用来展示数据

public MyViewHolder(View view) {
super(view);
tv_itemShow = (TextView) view.findViewById(R.id.tv_itemShow);
}
}
}

在MainActivity里头,我只截取重要的代码块,其他的都不是最重要的

产生数据源
List<String> list = new ArrayList<>();
for (int i = 0; i < 50; i++) {
list.add("------------>>" + i);
}


找到句炳和设置适配器
recyclerView = (RecyclerView) findViewById(R.id.recycleView);
recyclerView.setHasFixedSize(true);//item固定高度
recyclerView.setLayoutManager(new LinearLayoutManager(this));//设置默认的管理器
RecycleViewAdapter recycleViewAdapter = new RecycleViewAdapter(this, list);
recyclerView.setAdapter(recycleViewAdapter);

至此,RecycleView的工作就做好了。


下面是SwipeRefreshLayout的用法
同样在java文件中找到句炳,并设置监听
//        1、setOnRefreshListener(SwipeRefreshLayout.OnRefreshListener listener):设置手势滑动监听器。
// 2、setProgressBackgroundColor(int colorRes):设置进度圈的背景色。
// 3、setColorSchemeResources(int… colorResIds):设置进度动画的颜色。
// 4、setRefreshing(Boolean refreshing):设置组件的刷洗状态。
// 5、setSize(int size):设置进度圈的大小,只有两个值:DEFAULT、LARGE
//其余的属性自己去寻找就OK了
//这里要说明一点的是:我以为在SwipeRefreshLayout + RecyclerView两个一起,然后手势上下滚动
//系统会傻傻分不清,然后造成无法滑动RecyclerView,或者无法进行SwipeRefreshLayout刷新
//但是,今天我特意弄了两个同样有滑动手势的控件,看会不会产生冲突
//事实证明,系统帮我们作了区分,只有在RecyclerView到达了第一条数据顶部是,SwipeRefreshLayout才会起作用
refreshLayout = (SwipeRefreshLayout) findViewById(R.id.refreshLayout);
refreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
@Override
public void onRefresh() {
tv_refreshing.setVisibility(View.VISIBLE);
mHandler.postDelayed(new Runnable() {
@Override
public void run() {
Message msg = mHandler.obtainMessage();
msg.arg1 = 101;
mHandler.sendMessage(msg);
}
}, 2000);
}
});

我这里用了一个handler来操作,本来想用监听者的,但是太麻烦了,就没弄。

Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
if (msg.arg1 == 101) {
refreshLayout.setRefreshing(false);
tv_refreshing.setVisibility(View.INVISIBLE);
}
}
};

这里说明一下,refreshLayout.setRefreshing(false) 就是结束刷新的方法。
至此,刷新控件也算完成了。
以上纯属个人见解,各位看官如果有任何疑问,请与我联系。