RecyclerView详解

Android 5.0推出的同时,Google工程师在support-v7包下引入了一个全新的列表控件RecyclerView,这个控件比ListView和GridView都灵活,可用于显示庞大的数据。
三要素:adapter,LayoutManager ,数据源

  1. adapter :需要继承RecyclerView.Adapter ,作用是将数据与每一个item的界面进行绑定。
  2. LayoutManager :用来确定每一个item如何排列摆放,何时展示和隐藏。回收和重用一个view时,它会向适配器请求新的数据来替换旧的数据,从而避免了创建过多的view和频繁的调用findViewById()方法。 RecyclerView提供三种内置的布局管理器,有LinearLayoutManager(线性布局), GridLayoutManager (表格布局)和StaggeredGridLayoutManager(流式布局)。当然也可以自定义类继承RecyclerView.LayoutManager 实现自己想要的排列效果。
  3. 数据源:通常是list数据

下面是一个简单的示例代码:
activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
>
<android.support.v7.widget.RecyclerView
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:id="@+id/recycler"
    android:scrollbars="horizontal"
    />
</RelativeLayout>

MainActivity.java

public class MainActivity extends AppCompatActivity   {

private List <String> datas = new ArrayList<>();
private RecyclerView recyclerView;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    recyclerView = (RecyclerView) findViewById(R.id.recycler);
    initDatas();
    //创建流式布局
    StaggeredGridLayoutManager gridLayoutManager = new StaggeredGridLayoutManager(3,StaggeredGridLayoutManager.VERTICAL);
    assert recyclerView != null;
    recyclerView.setLayoutManager(gridLayoutManager);
    //如果item的高度固定,这样写提高效率
    recyclerView.setHasFixedSize(true);
    //创建并设置adapter
    MyAdapter myAdapter  = new MyAdapter(datas);
    recyclerView.setAdapter(myAdapter);
}

 public void initDatas(){
    datas.add( "美国");
    datas.add("比利时");
    datas.add("巴西");
    datas.add("意大利");
    datas.add( "葡萄牙");
    datas.add("西班牙");
    datas.add("克罗地亚");
 }
}

MyAdapter.java

public class MyAdapter extends RecyclerView.Adapter<MyAdapter.ViewHolder> {

public List<String> datas = null;
public MyAdapter(List<String> datas){
    this.datas = datas;
}

//创建新view被layoutManager所调用
@Override
public  ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
    LayoutInflater layoutInflater = LayoutInflater.from(parent.getContext());
    View view  = layoutInflater.inflate(R.layout.item,parent,false);
    ViewHolder vh = new ViewHolder(view);
    return vh;
}

//将数据与界面进行绑定
@Override
public void onBindViewHolder(ViewHolder viewHolder, int position) {
    viewHolder.textView.setText(datas.get(position));
}

//获取数据的数量
@Override
public int getItemCount() {
    return datas.size();
}

//自定义的ViewHolder,持有每个item的所有界面元素
public static class ViewHolder extends RecyclerView.ViewHolder{
    public TextView textView;
    public ViewHolder(View view){
        super(view);
        textView = (TextView) view.findViewById(R.id.text);
    }
}
}

item.xml

<?xml version="1.0" encoding="utf-8"?>
  <TextView
    android:id="@+id/text"
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:padding="10dp"
    android:gravity="center"
    android:textColor="#000000"
    android:textSize="16sp">
 </TextView>

不同布局应用示例:

  1. 横向布局 LinearLayoutManager layoutManager = new LinearLayoutManager (this); layoutManager .setOrientation(LinearLayoutManager.HORIZONTAL);
  2. Grid布局 GridLayoutManager layoutManager = new GridLayoutManager(this,3); recylerView.setLayoutManager(layoutManager);
  3. 瀑布流式布局见上述示例代码

为RecyclerView添加点击事件:

1.首先在Adaper文件中创建一个实现点击的接口,其中view是点击的item,data是数据,position是条目的位置,有了这些参数就可以定义下步操作了。

    public static interface OnRecyclerViewItemClickListener{
        void onItemClick(View view,String data,int position);
    }

2.定义完接口,在Adapter中添加接口和添加设置接口的方法:

private OnRecyclerViewItemClickListener onRecyclerViewItemClickListener = null;
public void setOnItemClickListener(OnRecyclerViewItemClickListener listener){
    this.onRecyclerViewItemClickListener = listener;
}

3.接口在Adapter中具体如何使用,如下所示:

public class MyAdapter extends RecyclerView.Adapter<MyAdapter.ViewHolder> implements View.OnClickListener{

public List<String> datas = null;
public MyAdapter(List<String> datas){
    this.datas = datas;
}

private OnRecyclerViewItemClickListener onRecyclerViewItemClickListener = null;
public void setOnItemClickListener(OnRecyclerViewItemClickListener listener){
    this.onRecyclerViewItemClickListener = listener;
}

//创建新view被layoutManager所调用
@Override
public  ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
    LayoutInflater layoutInflater = LayoutInflater.from(parent.getContext());
    View view  = layoutInflater.inflate(R.layout.item,parent,false);
    ViewHolder vh = new ViewHolder(view);
    view.setOnClickListener(this);
    return vh;
}

//将数据与界面进行绑定
@Override
public void onBindViewHolder(ViewHolder viewHolder, int position) {
    viewHolder.textView.setText(datas.get(position));
    viewHolder.itemView.setTag(position);
}

//获取数据的数量
@Override
public int getItemCount() {
    return datas.size();
}

//自定义的ViewHolder,持有每个item的所有界面元素
public static class ViewHolder extends RecyclerView.ViewHolder{
    public TextView textView;
    public ViewHolder(View view){
        super(view);
        textView = (TextView) view.findViewById(R.id.text);
    }
}

public static interface OnRecyclerViewItemClickListener{
    void onItemClick(View view,String data,int position);
}

@Override
public void onClick(View view) {
    if (onRecyclerViewItemClickListener != null){
        int position = (int) view.getTag();
        onRecyclerViewItemClickListener.onItemClick(view,datas.get(position),position);
    }
 }
}

4.做完这些就可以在MainActivity中添加点击事件了,具体如下:

MyAdapter myAdapter  = new MyAdapter(datas);
recyclerView.setAdapter(myAdapter);
myAdapter.setOnItemClickListener(new MyAdapter.OnRecyclerViewItemClickListener() {
  @Override
  public void onItemClick(View view, String data, int position) {
      Toast.makeText(getApplicationContext(),data,Toast.LENGTH_SHORT).show();
   }
});

5.RecyclerView中添加删除数据
liseview中增删数据的方法这里也有,但是这边还有更高级的,可以自带动画的删除或者增加条目。可以在MyAdapter中创建如下方法:

public void addItem(String content,int position){
  datas.add(position,content);
  notifyItemInserted(position);
}

public void removeItem(String content,int position){
  datas.remove(content);
  notifyItemRemoved(position);
}

注意这里更新数据集不用adapter.notifyDataSetChanged(),否则无动画效果。

还可以增加常用的下拉刷新功能,把要实现下拉刷新功能的控件放置到SwipRefreshLayout=中,就能让这个控件支持下拉刷新。下面是使用的示例:
activity_main.xml文件:

<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
>
<android.support.v4.widget.SwipeRefreshLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:id="@+id/swipe_refresh">

    <android.support.v7.widget.RecyclerView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:id="@+id/recycler"
        android:scrollbars="horizontal"
        />
</android.support.v4.widget.SwipeRefreshLayout>
</RelativeLayout>

MainActivity.java文件

public class MainActivity extends AppCompatActivity   {
List<String> datas = new ArrayList<>();
SwipeRefreshLayout swipeRefresh;
MyAdapter myAdapter;

@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    //下拉刷新
    swipeRefresh = (SwipeRefreshLayout) findViewById(R.id.swipe_refresh);
    swipeRefresh.setColorSchemeResources(R.color.colorPrimary);  //设置刷新进度条颜色
    swipeRefresh.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
        @Override
        public void onRefresh() {
            //处理刷新逻辑
            refresh();
        }
    });
}

//模拟网络交互
private void refresh(){
    new Thread(new Runnable() {
        @Override
        public void run() {
            try {
                Thread.sleep(2000);
            }catch (InterruptedException e){
                e.printStackTrace();
            }
            runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    myAdapter.notifyDataSetChanged();  //通知数据变化
                    swipeRefresh.setRefreshing(false);   //停止刷新
                }
            });
        }
    }).start();
}
//...
}

猜你喜欢

转载自blog.csdn.net/sunshine_a70/article/details/86169070