Android学习笔记--RecycleView用法

来源:互联网 发布:节奏大师网络拦截 编辑:程序博客网 时间:2024/05/22 03:48

1.什么是RecyclerView

RecyclerView是Android 5.0 materials design中的组件之一。通过名字我们就能看出一点端倪,没错,它主要的特点就是复用。我们知道,Listview中的Adapter中可以实现ViewHolder的复用。RecyclerView提供了一个耦合度更低的方式来复用ViewHolder,并且可以轻松的实现ListView、GridView以及瀑布流的效果。

2.RecycleView怎么引用

  Android Studio
dependencies {    compile 'com.android.support:recyclerview-v7:21.0.0'}
先介绍三个东西:

Adapter:使用RecyclerView之前,你需要一个继承自RecyclerView.Adapter的适配器,作用是将数据与每一个item的界面进行绑定

ViewHolder:用来保存视图引用的类.(这个与ListView可选不同,必须使用)

LayoutManager:用来确定每一个item如何进行排列摆放,何时展示和隐藏。回收或重用一个View的时候,LayoutManager会向适配器请求新的数据来替换旧的数据,这种机制避免了创建过多的View和频繁的调用findViewById方法(与ListView原理类似

3.基本用法

mRecyclerView = findView(R.id.id_recyclerview);mRecyclerView.setLayoutManager(layout);//设置布局管理器mRecyclerView.setAdapter(adapter)//设置adapter// 设置item动画mRecyclerView.setItemAnimator(new DefaultItemAnimator());//系统提供的默认动画


最简单的用法(效果ListView一样)

主布局:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:tools="http://schemas.android.com/tools"    android:layout_width="match_parent"    android:layout_height="match_parent" >    <android.support.v7.widget.RecyclerView        android:id="@+id/id_recyclerview"        android:layout_width="match_parent"        android:layout_height="match_parent" /></RelativeLayout>
Item的布局:

<LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android"    android:layout_width="match_parent"    android:background="#fff"    android:layout_height="wrap_content" >    <TextView        android:id="@+id/id_tv_item"        android:layout_width="match_parent"        android:layout_height="50dp"        android:gravity="center"        android:text="" /></LinearLayout>
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<String> 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<String>();        for (int i = 0; i < 30; i++)        {            mDatas.add("" +  i);        }    }    class HomeAdapter extends RecyclerView.Adapter<HomeAdapter.MyViewHolder>    {        @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);            }        }    }}

4.LayoutManager:

横向布局
如果想要一个横向的List只要设置LinearLayoutManager如下就行,注意要声明mLayoutManager的类型是LinearLayoutManager而不是父类LayoutManager:

mLayoutManager.setOrientation(LinearLayoutManager.HORIZONTAL);
Grid布局
如果想要一个Grid布局的列表,只要声明LayoutManager为GridLayoutManager即可:
mLayoutManager = new GridLayoutManager(context,columNum);mRecyclerView.setLayoutManager(mLayoutManager);
注意,在Grid布局中也可以设置列表的Orientation属性,来实现横向和纵向的Grid布局。

瀑布流布局
瀑布流就使用StaggeredGridLayoutManager吧,具体方法与上面类似,就不介绍了。

你还可以增加添加和删除数据的方法:

public void addData(int position) {        mDatas.add(position, "add add add");        notifyItemInserted(position);    }    public void removeData(int position) {            mDatas.remove(position);        notifyItemRemoved(position);    }


5.点击事件

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) {    }

其中第三个方法是处理触摸事件冲突的,跟我们没关系不用管它,前两个方法是不是很熟悉呢,这不就是View的事件分发机制里面的事件拦截和事件处理的两个方法吗,参数里为我们提供了触摸事件的数据MotionEvent,我们要做的就是去解析坐标点和触摸规律来识别触摸手势,然后获取触摸的是哪一个item,再执行我们的回调。

定义一个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的点击事件了:

@Overridepublic 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<String> 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<String>();        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<myAdapter.myHolder>{        @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了。


1 0
原创粉丝点击