在开发的过程中,我们经常使用ListView控件,但是ListView也有它的缺点,就是它不能够左右滑动数据,运行效率不高;
所以我们可以使用更强大的控件RecyclerView,可以说它是一个增强版的ListView,Google推荐使用,那就简单的使用一下这个控件。
因为RecyclerView是在support包中,所以我们要在build.gradle中添加该依赖。
compile 'com.android.support:recyclerview-v7:25.1.0'
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.example.dell.recyclerviewdemo.MainActivity">
<android.support.v7.widget.RecyclerView
android:id="@+id/recyc"
android:layout_width="match_parent"
android:layout_height="match_parent" />
RelativeLayout>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:padding="10dp">
<ImageView
android:id="@+id/item_img"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@mipmap/ic_launcher" />
<TextView
android:id="@+id/item_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginLeft="20dp"
android:text="Hello World!" />
LinearLayout>
/**
* Created by Dell on 2017/1/9.
*/
public class ItemVO {
private int mImg;
private String mName;
public ItemVO(int mImg, String mName) {
this.mImg = mImg;
this.mName = mName;
}
public void setmImg(int mImg) {
this.mImg = mImg;
}
public void setmName(String mName) {
this.mName = mName;
}
public int getmImg() {
return mImg;
}
public String getmName() {
return mName;
}
}
package com.example.adapter;
import android.support.v7.widget.RecyclerView;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import com.example.dell.recyclerviewdemo.R;
import com.example.vo.ItemVO;
import java.util.List;
/**
* Created by Dell on 2017/1/9.
*/
public class MyAdapter extends RecyclerView.Adapter<MyAdapter.ViewHolder>{
//动态数组
private List mList;
//构造
public MyAdapter(List mList) {
this.mList = mList;
}
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
//绑定行布局
View view = View.inflate(parent.getContext(),R.layout.item,null);
//实例化ViewHolder
ViewHolder holder = new ViewHolder(view);
return holder;
}
//设置数据
@Override
public void onBindViewHolder(ViewHolder holder, int position) {
//获取当前实体类对象
ItemVO vo = mList.get(position);
//设置
holder.text.setText(vo.getmName());
holder.img.setImageResource(vo.getmImg());
}
//数量
@Override
public int getItemCount() {
return mList.size();
}
//内部类
class ViewHolder extends RecyclerView.ViewHolder{
//行布局中的控件
ImageView img;
TextView text;
public ViewHolder(View itemView) {
super(itemView);
//绑定控件
img = (ImageView) itemView.findViewById(R.id.item_img);
text = (TextView) itemView.findViewById(R.id.item_text);
}
}
}
首先定义了一个内部类ViewHolder,继承RecyclerView.ViewHolder,然后定义两个两个全局变量,即行布局中的控件,然后再构造方法中绑定控件。
然后将适配器这个类继承RecyclerView.Adapter<内部类>,需要重写onCreateViewHolder()、onBindViewHolder()、getItemCount()这三个方法。
onCreateViewHolder():创建ViewHolder实例。
onBindViewHolder():对数据进行赋值。
getItemCount():返回有多少数据。
package com.example.dell.recyclerviewdemo;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import com.example.adapter.MyAdapter;
import com.example.vo.ItemVO;
import java.util.ArrayList;
import java.util.List;
public class MainActivity extends AppCompatActivity {
private RecyclerView mView;
private List mList = new ArrayList();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//绑定id
bindID();
//添加数据
addData();
//创建LinearLayoutManager
LinearLayoutManager manager = new LinearLayoutManager(this);
//设置
mView.setLayoutManager(manager);
//实例化适配器
MyAdapter myAdapter = new MyAdapter(mList);
//设置适配器
mView.setAdapter(myAdapter);
}
private void addData() {
for (int i = 0 ; i<50 ; i++){
ItemVO itemVO = new ItemVO(R.mipmap.ic_launcher, i + ":Hello World!");
//添加到数组
mList.add(itemVO);
itemVO = null;
}
}
private void bindID() {
mView = (RecyclerView) findViewById(R.id.recyc);
}
}
这里跟ListView的使用方式是差不多的。
使用一个addData()方法添加数据到mList,接着在onCreate()方法中首先获取到RecyclerView实例,然后创建出一个LinearLayoutManager对象,将让设置到RecyclerView当中。LinearLayoutManager用于指定RecyclerView的布局方式;然后实例化MyAdapter;最后绑定适配器。
这样,效果跟ListView实现是一样的。
因为是横向滑动,所以我们将行布局的宽度限定了。
xml version="1.0" encoding="utf-8"?>
"http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
<--! 限定宽度-->
android:layout_height="100dp"
android:orientation="vertical"
android:padding="10dp">
"@+id/item_img"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:src="@mipmap/ic_launcher" />
"@+id/item_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:text="Hello World!" />
在onCreate()中给LinearLayoutManager设置属性
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//绑定id
bindID();
//添加数据
addData();
//创建LinearLayoutManager
LinearLayoutManager manager = new LinearLayoutManager(this);
//设置为横向滑动
manager.setOrientation(LinearLayoutManager.HORIZONTAL);
//设置
mView.setLayoutManager(manager);
//实例化适配器
MyAdapter myAdapter = new MyAdapter(mList);
//设置适配器
mView.setAdapter(myAdapter);
}
运行后,就会实现这个横向滑动了。
这样,RecyclerView的优势就显示出来了,完成了ListVIew不能完成的任务。
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="5dp">
<ImageView
android:id="@+id/item_img"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:src="@mipmap/ic_launcher" />
<TextView
android:id="@+id/item_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:text="Hello World!" />
LinearLayout>
将行布局宽度更改为自定义。
package com.example.dell.recyclerviewdemo;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.StaggeredGridLayoutManager;
import com.example.adapter.MyAdapter;
import com.example.vo.ItemVO;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
public class MainActivity extends AppCompatActivity {
private RecyclerView mView;
private List mList = new ArrayList();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//绑定id
bindID();
//添加数据
addData();
// //创建LinearLayoutManager
// LinearLayoutManager manager = new LinearLayoutManager(this);
// //设置为横向滑动
// manager.setOrientation(LinearLayoutManager.HORIZONTAL);
//参数意思:分为几列;方向。
StaggeredGridLayoutManager manager = new StaggeredGridLayoutManager(3,StaggeredGridLayoutManager.VERTICAL);
//设置
mView.setLayoutManager(manager);
//实例化适配器
MyAdapter myAdapter = new MyAdapter(mList);
//设置适配器
mView.setAdapter(myAdapter);
}
private void addData() {
for (int i = 0; i < 50; i++) {
ItemVO itemVO = new ItemVO(R.mipmap.ic_launcher, getRandomStr(i + ":Hello World!"));
//添加到数组
mList.add(itemVO);
itemVO = null;
}
}
//将文本长度改变
private String getRandomStr(String str){
Random random = new Random();
int num = random.nextInt(10)+1;
StringBuilder builder = new StringBuilder();
for (int i = 0 ; i< num ;i++){
builder.append(str+"");
}
return builder.toString();
}
private void bindID() {
mView = (RecyclerView) findViewById(R.id.recyc);
}
}
将关于LinearLayoutManager的都注释掉,使用StaggeredGridLayoutManager对象。
因为瀑布流在textView数据长度不同的时候才能看到,所以我们就随机更该文本的长度,让瀑布流效果显示出来。
在RecyclerView中,没有提供给我们点击事件的方法,需要我们自己给子项具体的View去注册点击事件,相比ListView,这的确是比较麻烦,但是不代表RecyclerView不好,而是RecyclerView是人性化设计,可以根据自己的需要去设计,我们可以给每一个item设置监听,也可以给每一个TextView或其他设置监听。
给每个item 和 textView设置监听
package com.example.adapter;
import android.support.v7.widget.RecyclerView;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;
import com.example.dell.recyclerviewdemo.R;
import com.example.vo.ItemVO;
import java.util.List;
/**
* Created by Dell on 2017/1/9.
*/
public class MyAdapter extends RecyclerView.Adapter<MyAdapter.ViewHolder>{
//动态数组
private List mList;
//构造
public MyAdapter(List mList) {
this.mList = mList;
}
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
//绑定行布局
final View view = View.inflate(parent.getContext(),R.layout.item,null);
//实例化ViewHolder
final ViewHolder holder = new ViewHolder(view);
//item设置监听
holder.view.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//获取到position
int layoutPosition = holder.getLayoutPosition();
//土司
Toast.makeText(view.getContext(),"This is item :"+layoutPosition,Toast.LENGTH_SHORT).show();
}
});
//textView设置监听
holder.text.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//获取到position
int layoutPosition = holder.getLayoutPosition();
//土司
Toast.makeText(view.getContext(),"This is textView :"+layoutPosition,Toast.LENGTH_SHORT).show();
}
});
return holder;
}
//设置数据
@Override
public void onBindViewHolder(ViewHolder holder, int position) {
//获取当前实体类对象
ItemVO vo = mList.get(position);
//设置
holder.text.setText(vo.getmName());
holder.img.setImageResource(vo.getmImg());
}
//数量
@Override
public int getItemCount() {
return mList.size();
}
//内部类
class ViewHolder extends RecyclerView.ViewHolder{
//行布局中的控件
ImageView img;
TextView text;
//视图
View view;
public ViewHolder(View itemView) {
super(itemView);
view = itemView;
//绑定控件
img = (ImageView) itemView.findViewById(R.id.item_img);
text = (TextView) itemView.findViewById(R.id.item_text);
}
}
}
先修改了ViewHolder,在ViewHolder中添加了view变量来保存子项最外层布局实例,然后再onCreateViewHolder()中注册监听就好了。
这也是RecyclerView的强大之处,可以轻松的对子项中的任意控件设置点击事件。