RecyclerView+SwipeRefreshLayout
Google给我提供了一个很好的控件来取代listview。今天特意去弄了一下,因为这段时间忙,上次遗留下一个问题还没有解决,这些天是寝食不安啊。所以趁着今天有点空,所以就抽空重新看了下那个问题,终于解决了。(我这里遇到的问题是,RecyclerView数据错乱的问题)
这里喔顺便也把Google提供的自动刷新的控件也讲了,这个控件不难,但是很实用。我们在很多的app里面已经用上这个控件了。所以我们要跟上时代的步伐。
先上效果图:
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) 就是结束刷新的方法。
至此,刷新控件也算完成了。
以上纯属个人见解,各位看官如果有任何疑问,请与我联系。