RecyclerView这个控件也出来很久了,相信大家也学习的差不多了,如果还没学习的,或许我可以带领大家体验一把这个艺术般的控件。

项目已经同步至github:https://github.com/nanchen2251/recyclerViewDemo

据官方介绍,该控件是属于之间用的非常多的ListView和GridView的替代品,既然能替代用的如此普遍的它们,这自然有其该有的优势。

1)相对于ListView而言RecyclerView的优势体现在:

①封装了之前ListView的优化,封装了之前ViewHolder的复用,这样在自定义适配器的时候我们面向的不再是View,而是一个ViewHolder.

②提供了插板式的体验,高度解耦,异常灵活,针对每一项的显示抽取出了相应的类来控制每一个item的显示。若想实现网格视图或者瀑布流或者横向的ListView都可以通过制定不一样的LayoutManager来实现高大上的效果,这样就可以针对自己的业务逻辑随意发挥了。

③现在的RecyclerView对增删也有了动画的加入,并且你还可以自定义这些动画。

④对于Adaper适配器,现在刷新也增加了相应的方法,虽然之前的notifyDataSetChanged()同样可以实现这样的效果,但是每次刷新整个界面在数据多的时候必然会大大影响用户体验。所以Adapter增加了更新数据的方法notifyItemInserted和notifyItemRemoved,这样就可以在增删数据的时候只刷新被操作的Item,而且还加入了高大上的动画效果呢。

2)基本用法:

相信描述了这么多,你一定对这个神奇的控件迫不及待想尝试一波了。要用到这个RecyclerView很简单,首先在Gradle中添加支持包:

  1. compile 'com.android.support:recyclerview-v7:24.0.0'

下面就先来一个简单的用法,首先来Activity

  1. package com.example.nanchen.recyclerviewdemo;
  2.  
  3. import android.os.Bundle;
  4. import android.support.v7.app.AppCompatActivity;
  5. import android.support.v7.widget.DefaultItemAnimator;
  6. import android.support.v7.widget.LinearLayoutManager;
  7. import android.support.v7.widget.RecyclerView;
  8. import android.view.View;
  9. import android.widget.Toast;
  10.  
  11. import java.util.ArrayList;
  12. import java.util.List;
  13. import java.util.Locale;
  14.  
  15. public class MainActivity extends AppCompatActivity implements MyAdapter.OnRecyclerItemClickListener {
  16.  
  17. private MyAdapter adapter;
  18.  
  19. @Override
  20. protected void onCreate(Bundle savedInstanceState) {
  21. super.onCreate(savedInstanceState);
  22. setContentView(R.layout.activity_main);
  23.  
  24. RecyclerView recyclerView = (RecyclerView) findViewById(R.id.main_recycler);
  25. List<String> list = new ArrayList<>();
  26. for (int i = 0; i < 100; i++) {
  27. // list.add(String.format(Locale.CHINA, "第%03d条数据%s", i, i % 2 == 0 ? "" : "-----------------------"));
  28. list.add(String.format(Locale.CHINA, "第%03d条数据", i));
  29. }
  30. adapter = new MyAdapter(this, list);
  31. adapter.setOnRecyclerItemClickListener(this);
  32. recyclerView.setAdapter(adapter);
  33.  
  34. DefaultItemAnimator animator = new DefaultItemAnimator();
  35. animator.setRemoveDuration(1000);
  36. recyclerView.setItemAnimator(animator);
  37. //recyclerView.addItemDecoration(new MyDividerItemDecoration(this,MyDividerItemDecoration.VERTICAL_LIST));
  38.  
  39. //最后一个参数是反转布局一定是false,为true的时候为逆向显示,在聊天记录中可能会有使用
  40. //这个东西在显示后才会加载,不会像ScollView一样一次性加载导致内存溢出
  41. LinearLayoutManager layoutManager = new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false);
  42. recyclerView.setLayoutManager(layoutManager);
  43.  
  44. // GridLayoutManager gridLayoutManager = new GridLayoutManager(this, 3);
  45. // gridLayoutManager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() {
  46. // @Override
  47. // public int getSpanSize(int position) {
  48. // if (position == 0){
  49. // return 3;
  50. // }
  51. // return 1;
  52. // }
  53. // });
  54. // recyclerView.setLayoutManager(gridLayoutManager);
  55.  
  56. // StaggeredGridLayoutManager staggeredGridLayoutManager = new StaggeredGridLayoutManager(3, StaggeredGridLayoutManager.VERTICAL);
  57. // recyclerView.setLayoutManager(staggeredGridLayoutManager);
  58. }
  59.  
  60. @Override
  61. public void OnRecyclerItemClick(RecyclerView parent, View view, int position, String data) {
  62. Toast.makeText(this, data, Toast.LENGTH_SHORT).show();
  63. adapter.remove(position);
  64. }
  65. }

  在上面的Activity代码中,可见,我们需要自己指定LayoutManager,代码中用的是LinearLayoutMagener,你可以试试其他的。

再看看Adapter,有一个对大多数人来说很悲催的是,我们的ListView中一定会有的点击事件,而RecyclerView并没有提供这样的方法,这些点击事件都是需要我们自己学的,我这里Adapter就简单的实现了下,点击就会删除该Item。

  1. package com.example.nanchen.recyclerviewdemo;
  2.  
  3. import android.content.Context;
  4. import android.support.v7.widget.RecyclerView;
  5. import android.view.LayoutInflater;
  6. import android.view.View;
  7. import android.view.ViewGroup;
  8. import android.widget.TextView;
  9.  
  10. import java.util.List;
  11.  
  12. /**
  13. * 自定义RecyclerView的Adapter
  14. * Created by 南尘 on 16-7-15.
  15. */
  16. public class MyAdapter extends RecyclerView.Adapter<MyAdapter.ViewHolder> implements View.OnClickListener {
  17.  
  18. private Context context;
  19. private List<String> list;
  20. private OnRecyclerItemClickListener listener;
  21. private RecyclerView recyclerView;
  22.  
  23. public void setOnRecyclerItemClickListener(OnRecyclerItemClickListener listener) {
  24. this.listener = listener;
  25. }
  26.  
  27. public MyAdapter(Context context, List<String> list) {
  28. this.context = context;
  29. this.list = list;
  30. }
  31.  
  32. //在为RecyclerView提供数据的时候调用
  33. @Override
  34. public void onAttachedToRecyclerView(RecyclerView recyclerView) {
  35. super.onAttachedToRecyclerView(recyclerView);
  36. this.recyclerView = recyclerView;
  37. }
  38.  
  39. @Override
  40. public void onDetachedFromRecyclerView(RecyclerView recyclerView) {
  41. super.onDetachedFromRecyclerView(recyclerView);
  42. this.recyclerView = null;
  43. }
  44.  
  45. @Override
  46. public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
  47. View view = LayoutInflater.from(context).inflate(R.layout.item,parent,false);
  48. view.setOnClickListener(this);
  49. return new ViewHolder(view);
  50. }
  51.  
  52. @Override
  53. public void onBindViewHolder(ViewHolder holder, int position) {
  54. holder.text.setText(list.get(position));
  55. }
  56.  
  57. @Override
  58. public int getItemCount() {
  59. return list.size();
  60. }
  61.  
  62. @Override
  63. public void onClick(View v) {
  64. if (recyclerView != null && listener != null){
  65. int position = recyclerView.getChildAdapterPosition(v);
  66. listener.OnRecyclerItemClick(recyclerView,v,position,list.get(position));
  67. }
  68. }
  69.  
  70. /**
  71. * 删除指定数据
  72. * @param position 数据位置
  73. */
  74. public void remove(int position){
  75. list.remove(position);
  76. // notifyDataSetChanged();
  77. notifyItemRemoved(position);//这样就只会删除这一条数据,而不会一直刷
  78.  
  79. }
  80.  
  81. /**
  82. * 插入数据
  83. * @param position 插入位置
  84. * @param data 插入的数据
  85. */
  86. public void insert(int position,String data){
  87. list.add(position,data);
  88. notifyItemInserted(position);
  89.  
  90. }
  91.  
  92. public static class ViewHolder extends RecyclerView.ViewHolder{
  93.  
  94. private final TextView text;
  95.  
  96. public ViewHolder(View itemView) {
  97. super(itemView);
  98. text = (TextView) itemView.findViewById(R.id.item_text);
  99. }
  100. }
  101.  
  102. /**
  103. * 自定义RecyclerView的点击事件
  104. */
  105. interface OnRecyclerItemClickListener{
  106. void OnRecyclerItemClick(RecyclerView parent,View view,int position,String data);
  107. }
  108.  
  109. }

  继承这个Adapter需要指定一个ViewHolder的泛型,当然这个ViewHolder通常是由我们作为一个静态类自己写的。其他这个就像我们之前ListView中的BaseAdapter一样。

自己还可以实现其他的点击事件。

下面看下Xml,第一个是主布局,第二个是每一个项的布局,我这里就简单只实现一个TextView了。

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <RelativeLayout
  3. xmlns:android="http://schemas.android.com/apk/res/android"
  4. xmlns:tools="http://schemas.android.com/tools"
  5. xmlns:app="http://schemas.android.com/apk/res-auto"
  6. android:layout_width="match_parent"
  7. android:layout_height="match_parent"
  8. tools:context="com.example.nanchen.recyclerviewdemo.MainActivity">
  9.  
  10. <android.support.v7.widget.RecyclerView
  11. android:layout_width="match_parent"
  12. android:layout_height="match_parent"
  13. android:id="@+id/main_recycler"/>
  14.  
  15. </RelativeLayout>

  

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  3. android:layout_width="match_parent"
  4. android:layout_height="wrap_content"
  5. android:orientation="vertical">
  6.  
  7. <TextView
  8. android:id="@+id/item_text"
  9. android:textSize="30sp"
  10. android:layout_width="match_parent"
  11. android:layout_height="match_parent"/>
  12. </LinearLayout>

  这样运行出来你估计就会看到没有分割线,那么分割线怎么弄呢,看下文档,需要我们自己去写,这个网上有很多。

上一个我看到过很多次的。

  1. package com.example.nanchen.recyclerviewdemo;
  2.  
  3. import android.content.Context;
  4. import android.content.res.TypedArray;
  5. import android.graphics.Canvas;
  6. import android.graphics.Rect;
  7. import android.graphics.drawable.Drawable;
  8. import android.support.v7.widget.LinearLayoutManager;
  9. import android.support.v7.widget.RecyclerView;
  10. import android.view.View;
  11.  
  12. /**
  13. * Created by 南尘 on 16-7-15.
  14. */
  15. public class MyDividerItemDecoration extends RecyclerView.ItemDecoration {
  16. private static final int[] ATTRS = new int[]{
  17. android.R.attr. listDivider
  18. };
  19.  
  20. public static final int HORIZONTAL_LIST = LinearLayoutManager.HORIZONTAL;
  21.  
  22. public static final int VERTICAL_LIST = LinearLayoutManager.VERTICAL;
  23.  
  24. private Drawable mDivider;
  25.  
  26. private int mOrientation;
  27.  
  28. public MyDividerItemDecoration(Context context, int orientation) {
  29. final TypedArray a = context.obtainStyledAttributes(ATTRS );
  30. mDivider = a.getDrawable(0);
  31. a.recycle();
  32. setOrientation(orientation);
  33. }
  34.  
  35. public void setOrientation( int orientation) {
  36. if (orientation != HORIZONTAL_LIST && orientation != VERTICAL_LIST) {
  37. throw new IllegalArgumentException( "invalid orientation");
  38. }
  39. mOrientation = orientation;
  40. }
  41.  
  42. @Override
  43. public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) {
  44. if (mOrientation == VERTICAL_LIST) {
  45. drawVertical(c, parent);
  46. } else {
  47. drawHorizontal(c, parent);
  48. }
  49. }
  50.  
  51. public void drawVertical(Canvas c, RecyclerView parent) {
  52. final int left = parent.getPaddingLeft();
  53. final int right = parent.getWidth() - parent.getPaddingRight();
  54.  
  55. final int childCount = parent.getChildCount();
  56. for (int i = 0; i < childCount; i++) {
  57. final View child = parent.getChildAt(i);
  58. final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child
  59. .getLayoutParams();
  60. final int top = child.getBottom() + params.bottomMargin;
  61. final int bottom = top + mDivider.getIntrinsicHeight();
  62. mDivider.setBounds(left, top, right, bottom);
  63. mDivider.draw(c);
  64. }
  65. }
  66.  
  67. public void drawHorizontal(Canvas c, RecyclerView parent) {
  68. final int top = parent.getPaddingTop();
  69. final int bottom = parent.getHeight() - parent.getPaddingBottom();
  70.  
  71. final int childCount = parent.getChildCount();
  72. for (int i = 0; i < childCount; i++) {
  73. final View child = parent.getChildAt(i);
  74. final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child
  75. .getLayoutParams();
  76. final int left = child.getRight() + params.rightMargin;
  77. final int right = left + mDivider.getIntrinsicHeight();
  78. mDivider.setBounds(left, top, right, bottom);
  79. mDivider.draw(c);
  80. }
  81. }
  82.  
  83. @Override
  84. public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
  85. super.getItemOffsets(outRect, view, parent, state);
  86. if (mOrientation == VERTICAL_LIST) {
  87. outRect.set(0, 0, 0, mDivider.getIntrinsicHeight());
  88. }else{
  89. outRect.set(0, 0, mDivider.getIntrinsicWidth(), 0);
  90. }
  91. }
  92. }

  这样使用的是系统的分割线。

这样在Style中可以自己更改。

  1. <resources>
  2.  
  3. <!-- Base application theme. -->
  4. <style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
  5. <!-- Customize your theme here. -->
  6. <item name="colorPrimary">@color/colorPrimary</item>
  7. <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
  8. <item name="colorAccent">@color/colorAccent</item>
  9.  
  10. <item name="android:listDivider">@drawable/divider_bg</item>
  11. </style>
  12.  
  13. </resources>

  自定义一个Drawble

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <shape xmlns:android="http://schemas.android.com/apk/res/android"
  3. android:shape="rectangle" >
  4.  
  5. <gradient
  6. android:centerColor="#ff00ff00"
  7. android:endColor="#ff0000ff"
  8. android:startColor="#ffff0000"
  9. android:type="linear" />
  10. <size android:height="4dp"/>
  11.  
  12. </shape>

  别忘了去把之前我给的MainActivity.java中把分割线那句代码解去注释。

  1. //增加分割线
  2. recyclerView.addItemDecoration(new MyDividerItemDecoration(this,MyDividerItemDecoration.VERTICAL_LIST));

最后上一波简单的运行图吧。

 好了,我也说的不是很多,大家可以通过更多搜索出你想要的!

安卓v7支持包下的ListView替代品————RecyclerView的更多相关文章

  1. android listview 替代品recyclerview详解

    安卓v7支持包下的ListView替代品————RecyclerView   RecyclerView这个控件也出来很久了,相信大家也学习的差不多了,如果还没学习的,或许我可以带领大家体验一把这个艺术 ...

  2. 关于Andorid的RecyclerView在V7包下找不到的解决办法

      关于Andorid的RecyclerView在V7包下找不到的解决办法 最近在学习使用RecyclerView替换现有的ListView,看了几篇文章.当准备自己动手实现的时候发现,V7包下找不到 ...

  3. 装python package 时,conda提示会升级python2到python3,那可能是你的windows不支持py2env下的此包。

    装python package 时,conda提示会升级python2到python3, 那可能是你的windows不支持py2env下的此包.比如:win 下,tensorflow就不支持py2的环 ...

  4. V4 V7 V13支持包的区别(转)

    三者均为支持包,可以让低版本系统使用高版本特性,支持最小版本有差异 V4支持1.6以上 V7支持2.1以上 V13支持3.2以上 V7依赖V4 转自:

  5. Android v7包下Toolbar和ActionBarActivity实现后退导航效果

    android.support.v7包下的ToolBar和ActionBarActivity,均自带后退导航按钮,只是要手动开启,让它显示出来.先来看看ToolBar,页面前台代码: <andr ...

  6. V4 V7 V13支持包的区别

    三者均为支持包,可以让低版本系统使用高版本特性,支持最小版本有差异 V4支持1.6以上 V7支持2.1以上 V13支持3.2以上 V7依赖V4

  7. Android support library支持包常用控件介绍(二)

    谷歌官方推出Material Design 设计理念已经有段时间了,为支持更方便的实现 Material Design设计效果,官方给出了Android support design library ...

  8. Android Studio安卓导出aar包与Unity 3D交互

    Unity与安卓aar 包交互 本文提供全流程,中文翻译. Chinar 坚持将简单的生活方式,带给世人!(拥有更好的阅读体验 -- 高分辨率用户请根据需求调整网页缩放比例) Chinar -- 心分 ...

  9. android v7兼容包RecyclerView的使用(四)——点击事件的不同方式处理

    前三篇文章 android v7兼容包RecyclerView的使用(三)--布局管理器的使用 android v7兼容包RecyclerView的使用(二) android v7兼容包Recycle ...

随机推荐

  1. 【社工】NodeJS 应用仓库钓鱼

    前言 城堡总是从内部攻破的.再强大的系统,也得通过人来控制.如果将入侵直接从人这个环节发起,那么再坚固的防线,也都成为摆设. 下面分享一个例子,利用应用仓库,渗透到开发人员的系统中. 应用仓库 应用仓 ...

  2. JAVA for mac 的学习之路

    要学习一门新技术,首先得下载相关的工具. 一 . 下载相关工具 1. 下载 jdk formac 下载地址为:http://www.oracle.com/technetwork/java/javase ...

  3. Hyper-V3:虚拟机的配置

    在Hyper-V成功新建一台虚拟机,在正式使用之前,必须配置VM使用的硬件资源,并授予用户访问VM的权限等,本文罗列出一些常见的配置,供读者参阅. 一,为虚拟机分配使用的内存 在Hyper-V Man ...

  4. iOS开发之ReactiveCocoa下的MVVM(干货分享)

    最近工作比较忙,但还是出来更新博客了,今天给大家分享一些ReactiveCocoa以及MVVM的一些东西,干活还是比较足的.在之前发表过一篇博文,名字叫做<iOS开发之浅谈MVVM的架构设计与团 ...

  5. 如何在ASP.Net创建各种3D图表

    我们都知道,图表在ASP.NET技术中是一种特别受欢迎而又很重要的工具.图表是表示数据的图形,一般含有X和Y两个坐标轴.我们可以用折线,柱状,块状来表示数据.通过图表控件,我们即能表示数据又能比较各种 ...

  6. WebApi基于Token和签名的验证

    最近一段时间在学习WebApi,涉及到验证部分的一些知识觉得自己并不是太懂,所以来博客园看了几篇博文,发现一篇讲的特别好的,读了几遍茅塞顿开(都闪开,我要装逼了),刚开始读有些地方不理解,所以想了很久 ...

  7. 学习C的笔记

    [unsigned] 16位系统中一个int能存储的数据的范围为-32768~32767,而unsigned能存储的数据范围则是0~65535.由于在计算机中,整数是以补码形式存放的.根据最高位的不同 ...

  8. ILJMALL project过程中遇到Fragment嵌套问题:IllegalArgumentException: Binary XML file line #23: Duplicate id

    出现场景:当点击"分类"再返回"首页"时,发生error退出   BUG描述:Caused by: java.lang.IllegalArgumentExcep ...

  9. windows 2012 r2 can't find kb2919355

    问题   解决: 1.手动安装了 Windows8.1-KB2919442-x64 2.手动下载 KB2919355 更新成功     Turns out to have been a result ...

  10. AOP之Castle DynamicProxy 动态代理

    这里主要介绍使用castle这个动态代理,在.net一些开源的框架里可以找到它的影子,就连微软的rchard也是使用这个进行方法拦截等可以基于这个进行方法拦截,在这个方面PostSharp算是比较好用 ...