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中添加支持包:

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

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

package com.example.nanchen.recyclerviewdemo;

import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.DefaultItemAnimator;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.View;
import android.widget.Toast; import java.util.ArrayList;
import java.util.List;
import java.util.Locale; public class MainActivity extends AppCompatActivity implements MyAdapter.OnRecyclerItemClickListener { private MyAdapter adapter; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main); RecyclerView recyclerView = (RecyclerView) findViewById(R.id.main_recycler);
List<String> list = new ArrayList<>();
for (int i = 0; i < 100; i++) {
// list.add(String.format(Locale.CHINA, "第%03d条数据%s", i, i % 2 == 0 ? "" : "-----------------------"));
list.add(String.format(Locale.CHINA, "第%03d条数据", i));
}
adapter = new MyAdapter(this, list);
adapter.setOnRecyclerItemClickListener(this);
recyclerView.setAdapter(adapter); DefaultItemAnimator animator = new DefaultItemAnimator();
animator.setRemoveDuration(1000);
recyclerView.setItemAnimator(animator);
//recyclerView.addItemDecoration(new MyDividerItemDecoration(this,MyDividerItemDecoration.VERTICAL_LIST)); //最后一个参数是反转布局一定是false,为true的时候为逆向显示,在聊天记录中可能会有使用
//这个东西在显示后才会加载,不会像ScollView一样一次性加载导致内存溢出
LinearLayoutManager layoutManager = new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false);
recyclerView.setLayoutManager(layoutManager); // GridLayoutManager gridLayoutManager = new GridLayoutManager(this, 3);
// gridLayoutManager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() {
// @Override
// public int getSpanSize(int position) {
// if (position == 0){
// return 3;
// }
// return 1;
// }
// });
// recyclerView.setLayoutManager(gridLayoutManager); // StaggeredGridLayoutManager staggeredGridLayoutManager = new StaggeredGridLayoutManager(3, StaggeredGridLayoutManager.VERTICAL);
// recyclerView.setLayoutManager(staggeredGridLayoutManager);
} @Override
public void OnRecyclerItemClick(RecyclerView parent, View view, int position, String data) {
Toast.makeText(this, data, Toast.LENGTH_SHORT).show();
adapter.remove(position);
}
}

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

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

package com.example.nanchen.recyclerviewdemo;

import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView; import java.util.List; /**
* 自定义RecyclerView的Adapter
* Created by 南尘 on 16-7-15.
*/
public class MyAdapter extends RecyclerView.Adapter<MyAdapter.ViewHolder> implements View.OnClickListener { private Context context;
private List<String> list;
private OnRecyclerItemClickListener listener;
private RecyclerView recyclerView; public void setOnRecyclerItemClickListener(OnRecyclerItemClickListener listener) {
this.listener = listener;
} public MyAdapter(Context context, List<String> list) {
this.context = context;
this.list = list;
} //在为RecyclerView提供数据的时候调用
@Override
public void onAttachedToRecyclerView(RecyclerView recyclerView) {
super.onAttachedToRecyclerView(recyclerView);
this.recyclerView = recyclerView;
} @Override
public void onDetachedFromRecyclerView(RecyclerView recyclerView) {
super.onDetachedFromRecyclerView(recyclerView);
this.recyclerView = null;
} @Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(context).inflate(R.layout.item,parent,false);
view.setOnClickListener(this);
return new ViewHolder(view);
} @Override
public void onBindViewHolder(ViewHolder holder, int position) {
holder.text.setText(list.get(position));
} @Override
public int getItemCount() {
return list.size();
} @Override
public void onClick(View v) {
if (recyclerView != null && listener != null){
int position = recyclerView.getChildAdapterPosition(v);
listener.OnRecyclerItemClick(recyclerView,v,position,list.get(position));
}
} /**
* 删除指定数据
* @param position 数据位置
*/
public void remove(int position){
list.remove(position);
// notifyDataSetChanged();
notifyItemRemoved(position);//这样就只会删除这一条数据,而不会一直刷 } /**
* 插入数据
* @param position 插入位置
* @param data 插入的数据
*/
public void insert(int position,String data){
list.add(position,data);
notifyItemInserted(position); } public static class ViewHolder extends RecyclerView.ViewHolder{ private final TextView text; public ViewHolder(View itemView) {
super(itemView);
text = (TextView) itemView.findViewById(R.id.item_text);
}
} /**
* 自定义RecyclerView的点击事件
*/
interface OnRecyclerItemClickListener{
void OnRecyclerItemClick(RecyclerView parent,View view,int position,String data);
} }

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

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

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

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.example.nanchen.recyclerviewdemo.MainActivity"> <android.support.v7.widget.RecyclerView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/main_recycler"/> </RelativeLayout>

  

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"> <TextView
android:id="@+id/item_text"
android:textSize="30sp"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</LinearLayout>

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

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

package com.example.nanchen.recyclerviewdemo;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.View; /**
* Created by 南尘 on 16-7-15.
*/
public class MyDividerItemDecoration extends RecyclerView.ItemDecoration {
private static final int[] ATTRS = new int[]{
android.R.attr. listDivider
}; public static final int HORIZONTAL_LIST = LinearLayoutManager.HORIZONTAL; public static final int VERTICAL_LIST = LinearLayoutManager.VERTICAL; private Drawable mDivider; private int mOrientation; public MyDividerItemDecoration(Context context, int orientation) {
final TypedArray a = context.obtainStyledAttributes(ATTRS );
mDivider = a.getDrawable(0);
a.recycle();
setOrientation(orientation);
} public void setOrientation( int orientation) {
if (orientation != HORIZONTAL_LIST && orientation != VERTICAL_LIST) {
throw new IllegalArgumentException( "invalid orientation");
}
mOrientation = orientation;
} @Override
public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) {
if (mOrientation == VERTICAL_LIST) {
drawVertical(c, parent);
} else {
drawHorizontal(c, parent);
}
} public void drawVertical(Canvas c, RecyclerView parent) {
final int left = parent.getPaddingLeft();
final int right = parent.getWidth() - parent.getPaddingRight(); final int childCount = parent.getChildCount();
for (int i = 0; i < childCount; i++) {
final View child = parent.getChildAt(i);
final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child
.getLayoutParams();
final int top = child.getBottom() + params.bottomMargin;
final int bottom = top + mDivider.getIntrinsicHeight();
mDivider.setBounds(left, top, right, bottom);
mDivider.draw(c);
}
} public void drawHorizontal(Canvas c, RecyclerView parent) {
final int top = parent.getPaddingTop();
final int bottom = parent.getHeight() - parent.getPaddingBottom(); final int childCount = parent.getChildCount();
for (int i = 0; i < childCount; i++) {
final View child = parent.getChildAt(i);
final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child
.getLayoutParams();
final int left = child.getRight() + params.rightMargin;
final int right = left + mDivider.getIntrinsicHeight();
mDivider.setBounds(left, top, right, bottom);
mDivider.draw(c);
}
} @Override
public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
super.getItemOffsets(outRect, view, parent, state);
if (mOrientation == VERTICAL_LIST) {
outRect.set(0, 0, 0, mDivider.getIntrinsicHeight());
}else{
outRect.set(0, 0, mDivider.getIntrinsicWidth(), 0);
}
}
}

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

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

<resources>

    <!-- Base application theme. -->
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
<!-- Customize your theme here. -->
<item name="colorPrimary">@color/colorPrimary</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
<item name="colorAccent">@color/colorAccent</item> <item name="android:listDivider">@drawable/divider_bg</item>
</style> </resources>

  自定义一个Drawble

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle" > <gradient
android:centerColor="#ff00ff00"
android:endColor="#ff0000ff"
android:startColor="#ffff0000"
android:type="linear" />
<size android:height="4dp"/> </shape>

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

        //增加分割线
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. .NET跨平台之旅:将示例站点升级至 ASP.NET Core 1.1

    微软今天在 Connect(); // 2016 上发布了 .NET Core 1.1 ,ASP.NET Core 1.1 以及 Entity Framework Core 1.1.紧跟这次发布,我们 ...

  2. SQL Server 数据加密功能解析

    SQL Server 数据加密功能解析 转载自: 腾云阁 https://www.qcloud.com/community/article/194 数据加密是数据库被破解.物理介质被盗.备份被窃取的最 ...

  3. 如何远程关闭一个ASP.NET Core应用?

    在<历数依赖注入的N种玩法>演示系统自动注册服务的实例中,我们会发现输出的列表包含两个特殊的服务,它们的对应的服务接口分别是IApplicationLifetime和IHostingEnv ...

  4. node模块加载层级优化

    模块加载痛点 大家也或多或少的了解node模块的加载机制,最为粗浅的表述就是依次从当前目录向上级查询node_modules目录,若发现依赖则加载.但是随着应用规模的加大,目录层级越来越深,若是在某个 ...

  5. Log4net - 规则简介

    参考页面: http://www.yuanjiaocheng.net/CSharp/csharprumenshili.html http://www.yuanjiaocheng.net/entity/ ...

  6. c# Enumerable中Aggregate和Join的使用

    参考页面: http://www.yuanjiaocheng.net/ASPNET-CORE/asp.net-core-environment.html http://www.yuanjiaochen ...

  7. Missing Push Notification Entitlement 问题

    最近打包上传是遇到一个问题: 描述: Missing Push Notification Entitlement - Your app includes an API for Apple's Push ...

  8. IOS之Objective-C学习 ARC下的单例模式

    单例模式是我常用的一种设计模式,最常见的用途就是用来保存数据并且传递数据.这都归功于单例模式的特性,首先就让我为大家简单介绍一下单例模式的特性. 单例模式的三大特性: 1.某个类只能有一个实例: 2. ...

  9. AFN解析器里的坑

    AFN框架是用来用来发送网络请求的,它的好处是可以自动给你解析JSON数据,还可以发送带参数的请求AFN框架还可以监测当前的网络状态,还支持HTTPS请求,分别对用的类为AFNetworkReacha ...

  10. (转) 从0开始搭建SQL Server AlwaysOn 第三篇(配置AlwaysOn)

    原文地址: http://www.cnblogs.com/lyhabc/p/4682986.html 这一篇是从0开始搭建SQL Server AlwaysOn 的第三篇,这一篇才真正开始搭建Alwa ...