dependencies {
compile 'com.android.support:recyclerview-v7:21.0.0'
}
先介绍三个东西:
Adapter:使用RecyclerView之前,你需要一个继承自RecyclerView.Adapter的适配器,作用是将数据与每一个item的界面进行绑定
ViewHolder:用来保存视图引用的类.(这个与ListView可选不同,必须使用)
LayoutManager:用来确定每一个item如何进行排列摆放,何时展示和隐藏。回收或重用一个View的时候,LayoutManager会向适配器请求新的数据来替换旧的数据,这种机制避免了创建过多的View和频繁的调用findViewById方法(与ListView原理类似)
mRecyclerView = findView(R.id.id_recyclerview);
mRecyclerView.setLayoutManager(layout);//设置布局管理器
mRecyclerView.setAdapter(adapter)//设置adapter
// 设置item动画
mRecyclerView.setItemAnimator(new DefaultItemAnimator());//系统提供的默认动画
最简单的用法(效果ListView一样)
主布局:
Item的布局:
MainActiviyu:
import java.util.ArrayList;
import java.util.List;
import android.os.Bundle;
import android.support.v7.app.ActionBarActivity;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.RecyclerView.ViewHolder;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
public class MainActivity extends ActionBarActivity
{
private RecyclerView mRecyclerView;
private List mDatas;
private HomeAdapter mAdapter;
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_single_recyclerview);
initData();
mRecyclerView = (RecyclerView) findViewById(R.id.id_recyclerview);
mRecyclerView.setLayoutManager(new LinearLayoutManager(this));
mRecyclerView.setAdapter(mAdapter = new HomeAdapter());
}
protected void initData()
{
mDatas = new ArrayList();
for (int i = 0; i < 30; i++)
{
mDatas.add("" + i);
}
}
class HomeAdapter extends RecyclerView.Adapter
{
@Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType)
{
MyViewHolder holder = new MyViewHolder(LayoutInflater.from(
HomeActivity.this).inflate(R.layout.item_home, parent,
false));
return holder;
}
@Override
public void onBindViewHolder(MyViewHolder holder, int position)
{
holder.tv.setText(mDatas.get(position));
}
@Override
public int getItemCount()
{
return mDatas.size();
}
class MyViewHolder extends ViewHolder
{
TextView tv;
public MyViewHolder(View view)
{
super(view);
tv = (TextView) view.findViewById(R.id.id_num);
}
}
}
}
横向布局
如果想要一个横向的List只要设置LinearLayoutManager如下就行,注意要声明mLayoutManager的类型是LinearLayoutManager而不是父类LayoutManager:
mLayoutManager.setOrientation(LinearLayoutManager.HORIZONTAL);
Grid布局
mLayoutManager = new GridLayoutManager(context,columNum);
mRecyclerView.setLayoutManager(mLayoutManager);
注意,在Grid布局中也可以设置列表的Orientation属性,来实现横向和纵向的Grid布局。
你还可以增加添加和删除数据的方法:
public void addData(int position) {
mDatas.add(position, "add add add");
notifyItemInserted(position);
}
public void removeData(int position) {
mDatas.remove(position);
notifyItemRemoved(position);
}
RecyclerView的api发现虽然没有提供onItemClickListener但是提供了addOnItemTouchListener方法这里我有两种实现点击的方法。第一种是通过mRecyclerView.addOnItemTouchListener去监听然后去判断手势,第二种是通过adapter中自己去提供回调。
第一种:
1.定义一个类OnRecyclerItemClickListener实现OnItemTouchListener,我们需要实现其3个方法:
@Override
public boolean onInterceptTouchEvent(RecyclerView rv, MotionEvent e) {
}
@Override
public void onTouchEvent(RecyclerView rv, MotionEvent e) {
}
@Override
public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept) {
}
定义一个ItemTouchHelperGestureListener 继承自SimpleOnGestureListener ,实现onSingleTapUp方法:
private class ItemTouchHelperGestureListener extends GestureDetector.SimpleOnGestureListener {
@Override
public boolean onSingleTapUp(MotionEvent e) {
}
}
获取到了RecyclerView的点击事件和触摸事件数据MotionEvent ,那么我们怎么知道点击的是哪一个item呢?RecyclerView已经为我们提供了这样的方法:findChildViewUnder(),我们可以通过这个方法获得点击的item,同时我们调用RecyclerView的另一个方法getChildViewHolder(),可以获得该item的ViewHolder,最后再回调我们定义的虚方法onItemClick()就ok了,这样我们就可以在外部实现该方法来获得item的点击事件了:
@Override
public boolean onSingleTapUp(MotionEvent e) {
View child = recyclerView.findChildViewUnder(e.getX(), e.getY());
if (child!=null) {
RecyclerView.ViewHolder vh = recyclerView.getChildViewHolder(child);
onItemClick(vh);
}
return true;
}
完整代码如下:
public class MainActivity extends AppCompatActivity {
private RecyclerView mRecyclerView;
private List mData;
private myAdapter mAdapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initData();
mRecyclerView= (RecyclerView) findViewById(R.id.recycleView);
mRecyclerView.setLayoutManager(new LinearLayoutManager(this));
//如果可以确定每个item的高度是固定的,设置这个选项可以提高性能
mRecyclerView.setHasFixedSize(true);
mRecyclerView.setAdapter(mAdapter=new myAdapter());
mRecyclerView.addOnItemTouchListener(new onRecycleItemClickListener(mRecyclerView) {
@Override
public void onItemClick(RecyclerView.ViewHolder vh) {
//具体点击事件
Toast.makeText(MainActivity.this, "hah",Toast.LENGTH_SHORT).show();
}
});
}
private void initData(){
mData=new ArrayList();
for (int i = 'A'; i < 'Z'; i++) {
mData.add(""+(char)i);
}
}
public abstract class onRecycleItemClickListener implements RecyclerView.OnItemTouchListener{
private GestureDetector mGestureDetector;
private RecyclerView recycleView;
@Override
public boolean onInterceptTouchEvent(RecyclerView rv, MotionEvent e) {
mGestureDetector.onTouchEvent(e);
return false;
}
//处理触摸冲突的方法
@Override
public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept) {
}
@Override
public void onTouchEvent(RecyclerView rv, MotionEvent e) {
mGestureDetector.onTouchEvent(e);
}
public onRecycleItemClickListener(RecyclerView recycleView) {
this.recycleView = recycleView;
mGestureDetector=new GestureDetector(MainActivity.this,new ItemTouchHelperGestureListener());
}
private class ItemTouchHelperGestureListener extends GestureDetector.SimpleOnGestureListener{
@Override
public boolean onSingleTapUp(MotionEvent e) {
View view=recycleView.findChildViewUnder(e.getX(),e.getY());
if (view!=null){
RecyclerView.ViewHolder holder=recycleView.getChildViewHolder(view);
onItemClick(holder);
}
return true;
}
//长点击事件,本例不需要不处理
//@Override
//public void onLongPress(MotionEvent e) {
// View child = recyclerView.findChildViewUnder(e.getX(), e.getY());
// if (child!=null) {
// RecyclerView.myHolder vh = recyclerView.getChildViewHolder(child);
// onItemLongClick(vh);
// }
//}
}
public abstract void onItemClick(RecyclerView.ViewHolder vh);
//public abstract void onItemLongClick(RecyclerView.myHolder vh);
}
public class myAdapter extends RecyclerView.Adapter{
@Override
public myHolder onCreateViewHolder(ViewGroup parent, int viewType) {
myHolder holder=new myHolder(LayoutInflater.from(MainActivity.this).inflate(R.layout.item,parent,
false));
return holder;
}
@Override
public void onBindViewHolder(myHolder holder, int position) {
holder.item_tv.setText(mData.get(position));
}
//添加item
public void addItem(int position){
mData.add(position,"insert one");
notifyItemInserted(position);
}
//删除item
public void removeData(int position){
mData.remove(position);
notifyItemRemoved(position);
}
@Override
public int getItemCount() {
return mData.size();
}
public class myHolder extends RecyclerView.ViewHolder{
TextView item_tv;
public myHolder(View itemView) {
super(itemView);
item_tv= (TextView) itemView.findViewById(R.id.item_tv);
}
}
}
}
第二种方法:
这个代码比较简单,先在RecyclerView.Adapter中添加回调接口:
public interface OnItemClickLitener
{
void onItemClick(View view, int position);
void onItemLongClick(View view , int position);
}
private OnItemClickLitener mOnItemClickLitener;
public void setOnItemClickLitener(OnItemClickLitener mOnItemClickLitener)
{
this.mOnItemClickLitener = mOnItemClickLitener;
}
@Override
public void onBindViewHolder(final MyViewHolder holder, final int position)
{
holder.tv.setText(mDatas.get(position));
// 如果设置了回调,则设置点击事件
if (mOnItemClickLitener != null)
{
holder.itemView.setOnClickListener(new OnClickListener()
{
@Override
public void onClick(View v)
{
int pos = holder.getLayoutPosition();
mOnItemClickLitener.onItemClick(holder.itemView, pos);
}
});
holder.itemView.setOnLongClickListener(new OnLongClickListener()
{
@Override
public boolean onLongClick(View v)
{
int pos = holder.getLayoutPosition();
mOnItemClickLitener.onItemLongClick(holder.itemView, pos);
return false;
}
});
}
}
然后再Activity中设置监听:
mAdapter.setOnItemClickLitener(new OnItemClickLitener()
{
@Override
public void onItemClick(View view, int position)
{
Toast.makeText(HomeActivity.this, position + " click",
Toast.LENGTH_SHORT).show();
}
@Override
public void onItemLongClick(View view, int position)
{
Toast.makeText(HomeActivity.this, position + " long click",
Toast.LENGTH_SHORT).show();
mAdapter.removeData(position);
}
});
就OK了。