【Android 界面效果47】RecyclerView详解

RecylerView作为 support-library发布出来,这对开发者来说绝对是个好消息。因为可以在更低的Android版本上使用这个新视图。下面我们看如何获取 RecylerView。首先打开Android SDK Manager,然后更新Extras->Android Support Library即可。

然后在本地../sdk/extras/android/support/v7中找到recyclerview。我已经将下载好的Recyclerview整理成一个Eclipse可编译的Library工程上传到Github,有需求的同学请戳链接


示例程序

我将通过
RecylerView制作一个横向滑动的“ListView”,下面是示例程序的截图。并在ActionBar上设置数据的添加/删除操作。请同学们注
意,RecyclerView的接口Google可能会继续优化和修改,所以最终的版本可能和我提供的程序有出入。Demo程序Github链接


为什么要使用RecyclerView?

Google在是这样描述RecyclerView的:

"A flexible view for providing a limited window into a large data set."


以RecyclerView适用于无法在一个屏幕范围内展现格式一样的数据时,需要用多行或多列来展示。例如展示联系人,图片,视频等。用户需要滑动屏幕
来查看数据,这时RecyclerView的特性就有用武之地了。比如,当用户滑动使当前一个可视的Item滑出屏幕,这个Item的视图将会被回收并在
一个新Item进入可视范围后重新被使用。

如下图所示,用户滑动向上滑动左边的RecyclerView,No.0和No.1就会滑出屏幕可视范围,这时右图的No.0和No.1的视图将会被RecyclerView放入一个可重复利用的缓存中以备再次使用。

可回收利用View是个很实用的功能,它不仅可以减少CPU不断inflate View的开销,而且可以节省缓存View的内存开销。


时,你可能会问:这不是一个新功能啊!是的,我们已经在使用ListView的时候使用了这个机制,但是当使用ListView时,显示,回收等功能是紧
密耦合在一起的,Google现在发布RecyclerView,使方法更灵活,开发者也能自定义各种各样的显示效果。


RecyclerView不再负责显示工作

和ListView不一样的是,RecyclerView不再负责Item的摆放等显示方面的功能。所有和布局、绘制等方面的工作Google都其拆分成不同的类进行管理。所以开发者可以自定义各种各样满足定制需求的的功能类。

下面是一些和RecyclerView相关的非常重要的类列表。

RecyclerView相关类
类名 说明
RecyclerView.Adapter 托管数据集合,为每个Item创建视图

RecyclerView.ViewHolder 承载Item视图的子视图
RecyclerView.LayoutManager 负责Item视图的布局
RecyclerView.ItemDecoration 为每个Item视图添加子视图,在Demo中被用来绘制Divider
RecyclerView.ItemAnimator 负责添加、删除数据时的动画效果

ViewHolder

关于ViewHolder,Google早就推荐开发者使用,但也只是建议。但是现在,RecyclerView.Adapter最终要求开发者必须使用ViewHolder。如果你还对ViewHolder不了解,请阅读Android
training session

Demo通过继承RecyclerView.ViewHolder来实现自定义:

    public class MyViewHolder extends ViewHolder implements OnClickListener,OnLongClickListener{  

        public ImageView iv;
        public TextView tv;
        private MyItemClickListener mListener;
        private MyItemLongClickListener mLongClickListener;  

        public MyViewHolder(View rootView,MyItemClickListener listener,MyItemLongClickListener longClickListener) {
            super(rootView);
            iv = (ImageView)rootView.findViewById(R.id.item_iv);
            tv = (TextView)rootView.findViewById(R.id.item_tv);
            this.mListener = listener;
            this.mLongClickListener = longClickListener;
            rootView.setOnClickListener(this);
            rootView.setOnLongClickListener(this);
        }  

        /**
         * 点击监听
         */
        @Override
        public void onClick(View v) {
            if(mListener != null){
                mListener.onItemClick(v,getPosition());
            }
        }  

        /**
         * 长按监听
         */
        @Override
        public boolean onLongClick(View arg0) {
            if(mLongClickListener != null){
                mLongClickListener.onItemLongClick(arg0, getPosition());
            }
            return true;
        }  

    }  

RecyclerView.Adapter

Adapter负责扮演两个角色:不仅为底部数据提供支持而且还负责为数据创建合适的视图。Adapter适用在Android很多控件,例如ListView、AutoCompleteTextView等。
继承RecyclerView.Adapter需要实现以下三个方法:

  • public ViewHolder onCreateViewHolder(ViewGroup parent,int viewType)
  • public void onBindViewHolder(ViewHolder holder,int position)
  • public int getItemCount()

Demo中的Adapter:

    public class MyAdapter extends Adapter<MyViewHolder> {  

        private List<MyItemBean> mData;
        private MyItemClickListener mItemClickListener;
        private MyItemLongClickListener mItemLongClickListener;  

        public MyAdapter(List<MyItemBean> data){
            this.mData = data;
        }  

        @Override
        public int getItemCount() {
            return mData.size();
        }  

        @Override
        public void onBindViewHolder(MyViewHolder holder, int position) {
            MyItemBean bean = mData.get(position);
            holder.tv.setText(bean.tv);
        }  

        @Override
        public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
            View itemView = LayoutInflater.from(parent.getContext()).inflate(R.layout.item, parent,false);
            MyViewHolder vh = new MyViewHolder(itemView,mItemClickListener,mItemLongClickListener);
            return vh;
        }
   }

onCreateViewHolder中负责为Item创建视图,onBindViewHolder负责将数据绑定到Item的视图上。

RecyclerView.LayoutManager

LayoutManager是
RecyclerView中最有意思的类。该类负责将每个Item视图在RecylerView中的布局。目前Google提供了
LayoutManager的一个子类:LinearLayoutManager。LinearLayoutManager提供了横向和竖向两种布
局,Demo就是使用LinearLayoutManger的横向布局实现的。

如果要自定义LayoutManager,需要实现一个abstract方法

  • public LayoutParams generateDefaultLayoutParams()

Demo中为RecylerView添加LinearLayoutManager的片段:

         MyLayoutManager manager = new MyLayoutManager(this);
            manager.setOrientation(LinearLayout.HORIZONTAL);//默认是LinearLayout.VERTICAL
            mRecyclerView.setLayoutManager(manager);  

LinearLayoutManager提供了如下几个方法来帮助开发者获取屏幕上的顶部item和底部item:

  • findFirstVisibleItemPosition()
  • findFirstCompletelyVisibleItemPosition()
  • findLastVisibleItemPosition()
  • findLastCompletelyVisibleItemPosition()


RecyclerView.ItemDecoration

通过
ItemDecoration可以使各个Item在视觉上相互分开,其实和ListView的Divider很像。ItemDecoration并不是
RecyclerView必须设置的,开发者可以不设置或者设置多个Decoration。RecyclerView会遍历所有的
ItemDecoration并调用各自的绘图方法。

继承ItemDecoration需要实现以下三个方法:

  • public void onDraw(Canvas c,RecyclerView parent,RecyclerView.State state)
  • public void getItemOffset(Rect outRect,int itemPosition,RecyclerView parent)

LayoutManager会调用getItemOffset方法来计算每个Item的Decoration合适的尺寸。

Demo中自定义了一个ItemDecoration来实现ListView的Divider效果:

    public class MyDecoration extends ItemDecoration {  

        private static final int[] ATTRS = new int[]{
            android.R.attr.listDivider
        };  

        private Drawable mDivider;  

        public MyDecoration(Context ctx){
            final TypedArray a = ctx.obtainStyledAttributes(ATTRS);
            mDivider = a.getDrawable(0);
        }  

        @Override
        public void onDraw(Canvas c, RecyclerView parent, State state) {
            int top = parent.getPaddingTop();
            int bottom = parent.getHeight() - parent.getPaddingBottom();
            int childCount = parent.getChildCount();
            for(int i=0;i < childCount;i++){
                View child = parent.getChildAt(i);
                RecyclerView.LayoutParams layoutParams = (RecyclerView.LayoutParams)child.getLayoutParams();
                int left = child.getRight() + layoutParams.rightMargin;
                int right = left + mDivider.getIntrinsicWidth();
                mDivider.setBounds(left, top, right, bottom);
                mDivider.draw(c);
            }
        }  

        @Override
        public void getItemOffsets(Rect outRect, View view, RecyclerView parent,
                State state) {
            outRect.set(0, 0, mDivider.getIntrinsicWidth(), 0);
        }  

    }  

RecyclerView.ItemAnimatior

当Item有以下三种操作时ItemAnimatior会为RecyclerView提供动画效果:

  • 删除某一个Item
  • 添加一个新的Item
  • 移动某个Item

Google提供了一个名为DefaultItemAnimator的默认ItemAnimator供开发者使用。如果开发者不为RecyclerView设置ItemAnimator,RecyclerView也会使用默认的DefaultItemAnimator。

显 然,为了让动画效果起效,开发者必须通知Adapter数据有改变。之前我们使用Adapter时会调用notifyDataSetChanged()来 通知Adapter数据改变并更新视图,现在RecyclerView,Adapter提供了许多notifyXyz()方法,例如Demo中使用了以下 两个方法:

  • public final void notifyItemInserted(int position)
  • public final void notifyItemRemoved(int position)


使用RecyclerView

首先,我们先看如何在xml中使用RecyclerView

    <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"
        tools:context="com.xmy.recylerviewdemo.MainActivity" >  

        <android.support.v7.widget.RecyclerView
            android:id="@+id/recyclerView"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"/>  

    </RelativeLayout>  

然后需要开发者在代码中实现RecyclerView的组装,大体可概括为以下步骤:

  • 实例化RecyclerView
  • 为RecyclerView设置LayoutManager
  • 为RecyclerView设置Adapater
  • 如果有需求,可以设置一个或多个ItemDecorations,当然,也可以不设置
  • 如果有需求,可以设置ItemAnimator

以上就是对RecyclerView的基本介绍,下篇博客会讲RecyclerView如何像ListView一样为Item设置交互监听。

参考资料:

A First Glance at Android’s RecyclerView

原文:http://blog.csdn.net/guxiao1201/article/details/40399777

时间: 2024-09-30 17:01:26

【Android 界面效果47】RecyclerView详解的相关文章

android L新控件RecyclerView详解与DeMo

介绍 在谷歌的官网我们可以看到它是这样介绍的:RecyclerView is a more advanced and flexible version of ListView. This widget is a container for large sets of views that can be recycled and scrolled very efficiently. Use the RecyclerView widget when you have lists with eleme

Android Design Support Library使用详解

Android Design Support Library使用详解 Google在2015的IO大会上,给我们带来了更加详细的Material Design设计规范,同时,也给我们带来了全新的Android Design Support Library,在这个support库里面,Google给我们提供了更加规范的MD设计风格的控件.最重要的是,Android Design Support Library的兼容性更广,直接可以向下兼容到Android 2.2.这不得不说是一个良心之作. 使用S

Android软件开发之TextView详解

Android软件开发之TextView详解<IGNORE_JS_OP> TextView的API 中文文档中 说明它的结构 结构java.lang.Object   android.view.View        android.widget.TextView直接子类:    Button, CheckedTextView, Chronometer, DigitalClock, EditText间接子类:     AutoCompleteTextView, CheckBox, Compou

Android activity四大启动模式详解

Activity中四大启动模式 在AndroidManifest.xml中 ,有一个默认的activity  在它里面可以设置activity启动模式,  android:launchMode=""  ,该属性用于配置Activity的加载模式,该属性支持4中属性  每不同的模式出现不同的效果,下面详解启动模式. standard:标准模式,默认加载模式 singleTop:Task顶单例模式 singleTask:Task内单例模式 singleInstance:全局单单例模式 1

Android开发之通知栏Notification详解

Notification的用法  --- 状态栏通知 发送一个状态栏通知必须的两个类: 1. NotificationManager   --- 状态栏通知的管理类,负责发通知,清除通知等 NotificationManager : 是一个系统Service,必须通过 context.getSystemService(NOTIFICATION_SERVICE)方法获取 NotificationManager notificationManager = (NotificationManager)

Android开发之SoundPool使用详解

使用SoundPool播放音效 如果应用程序经常播放密集.急促而又短暂的音效(如游戏音效)那么使用MediaPlayer显得有些不太适合了.因为MediaPlayer存在如下缺点: 1)         延时时间较长,且资源占用率高. 2)         不支持多个音频同时播放. Android中除了MediaPlayer播放音频之外还提供了SoundPool来播放音效,SoundPool使用音效池的概念来管理多个短促的音效,例如它可以开始就加载20个音效,以后在程序中按音效的ID进行播放.

[Android新手区] SQLite 操作详解--SQL语法

该文章完全摘自转自:北大青鸟[Android新手区] SQLite 操作详解--SQL语法  :http://home.bdqn.cn/thread-49363-1-1.html SQLite库可以解析大部分标准SQL语言.但它也省去了一些特性并且加入了一些自己的新特性.这篇文档就是试图描述那些SQLite支持/不支持的SQL语法的.查看关键字列表. 如下语法表格中,纯文本用蓝色粗体显示.非终极符号为斜体红色.作为语法一部分的运算符用黑色Roman字体表示. 这篇文档只是对SQLite实现的SQ

Android Animations 视图动画使用详解!!!

转自:http://www.open-open.com/lib/view/open1335777066015.html Android Animations 视图动画使用详解 一.动画类型 Android的animation由四种类型组成:alpha.scale.translate.rotate XML配置文件中 alpha 渐变透明度动画效果 scale 渐变尺寸伸缩动画效果 translate 画面转换位置移动动画效果 rotate 画面转移旋转动画效果 Java Code代码中 Alpha

Android Service demo例子使用详解

Android Service demo例子使用详解\ 概述Service 是 Android 的四大组件之一,它主要的作用是后台执行操作,Activity 属于带有 UI 界面跟用户进行交互,而 Service 则没有 UI 界面,所有的操作都是基于后台运行完成.并且 Service 跟 Activity 一样也是可以由其它的应用程序调用启动的,而且就算用户切换了应用程序,Service 依旧保持运行.一个组件如果与 Service 进行了绑定( bind ),就可以跟 Service 进行数