Android5.0 v7扩展包之RecyclerView
Android开发文章
android
RecyclerView
近日Google发布了Android5.0 SDK,随之android L的部分预览功能也发布了正式版本。本文将介绍RecyclerView
。
RecylerView
简介
The RecyclerView widget is a more advanced and flexible version of ListView. This widget is aContainer
for displaying large data sets that can be scrolled very efficiently by maintaining a limited number of views. Use the RecyclerView widget when you have data collections whose elements change at runtime based on user action or network events.
大意是RecylerView
是一个高级的ListView
。可以很好的维护大数据集的滚动和显示。详细的解释参考这里。本文的内容也是基于此而写。
RecylerView
在那里
- 包名:
android.support.v7.widget.RecyclerView
- 文件地址有两个
- 1:
android-sdk/extras/android/m2repository/com/android/support/recyclerview-v7
- 2:
android-sdk/extras/android/support/v7/recyclerview
- 1:
RecylerView
怎么引用
Android Studio
<span style="font-size:18px;">dependencies { compile 'com.android.support:recyclerview-v7:21.0.0' }</span>
在此推荐使用Android
开发Android项目
Studio
Eclipse
以下猜测可以使用,没有经过测试。
- 在
android-sdk/extras/android/support/v7/recyclerview
目录下面有libs
,里面有jar包,引用此jar包。 - 在
android-sdk/extras/android/m2repository/com/android/support/recyclerview-v7
目录下根据版本号21.0.0
目录可以找到一个名为recyclerview-v7-21.0.0.aar
的文件。解压此文件里面有classes.jar
,引用此jar包。
找不到目录
针对找不到目录的同学,打开Android SDK Manager把最新的资源更新下来即可。
RecylerView
新类介绍
说说几个新类,Adapter(android.support.v7.widget.RecyclerView.Adapter)
、ViewHolder(android.support.v7.widget.RecyclerView.ViewHolder)
、LayoutManager(android.support.v7.widget.RecyclerView.LayoutManager)
Adapter
适配器,和以前的Adapter不一样,此Adapter为RecylerView特有。作为一个抽象类,有以下几个抽象方法。
public static abstract class Adapter<VH extends ViewHolder>{}{ ... public abstract VH onCreateViewHolder(ViewGroup parent, int viewType); public abstract void onBindViewHolder(VH holder, int position); public abstract int getItemCount(); ... }
方法onCreateViewHolder
直接创建一种可复用的VH
或者根据viewType
创建多种VH
。
方法onBindViewHolder
数据和VH
通过位置position
绑定
方法getItemCount
返回有多少条数据
ViewHolder
同样是一个抽象类,我们通过继承此类实现view的封装。
LayoutManager
布局管理器,RecylerView
中数据显示布局方式。目前v7包种提供了三种模式,分别是LinearLayoutManager
、GridLayoutManager
、StaggeredGridLayoutManager
。
LinearLayoutManager
线性布局,通过方向VERTICAL
和HORIZONTAL
可以实现垂直和水平的效果。默认为VERTICAL
垂直方向。
通过此布局可以实现ListView的效果。垂直方向为普通的ListView
显示效果,水平方向即是水平滑动的ListView
。
GridLayoutManager
网格布局,继承于LinearLayoutManager
,可以指定有几行和方向。
通过此布局可以实现GridView
的效果,同样有垂直方向和水平方向。
StaggeredGridLayoutManager
交错网格布局,类似于网格布局,但每个格子的高度或者长度可以不一样。
俗称的瀑布流效果,同样有垂直方向和水平方向。
实例代码
实例代码会列出一个完整的通过RecylerView
、LinearLayoutManager
、Adapter
、ViewHolder
实现一个普通的ListView
数据显示效果,之后修改部分代码实现不同的效果。
ListView
引入的包
dependencies { compile fileTree(dir: 'libs', include: ['*.jar']) compile 'com.android.support:appcompat-v7:21.0.0' compile 'com.nostra13.universalimageloader:universal-image-loader:1.9.3' compile 'com.android.support:recyclerview-v7:21.0.0' compile 'org.roboguice:roboguice:2.0' compile 'com.android.support:palette-v7:21.0.0' }
Activity
package com.lizheng.recylerviewdemo; import android.os.Bundle; import android.os.Handler; import android.support.v4.widget.SwipeRefreshLayout; import android.support.v7.widget.GridLayoutManager; import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.RecyclerView; import android.support.v7.widget.StaggeredGridLayoutManager; import roboguice.activity.RoboFragmentActivity; import roboguice.inject.InjectView; public class MainActivity extends RoboFragmentActivity { @InjectView(R.id.recyclerView) private RecyclerView recyclerView; @InjectView(R.id.swipeLayout) private SwipeRefreshLayout swipeLayout; private DemoAdapter adapter; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.ac_main); adapter = new DemoAdapter(C.picUrls); // 线性布局管理器 LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this); // 设置布局管理器 recyclerView.setLayoutManager(linearLayoutManager); recyclerView.setAdapter(adapter); // 模拟下拉刷新 swipeLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() { @Override public void onRefresh() { new Handler().postDelayed(new Runnable() { @Override public void run() { swipeLayout.setRefreshing(false); adapter.notifyDataSetChanged(); } }, 2000); } }); } }
Adapter
和ViewHolder
package com.lizheng.recylerviewdemo; import android.support.v7.widget.RecyclerView; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.ImageView; import android.widget.TextView; import com.nostra13.universalimageloader.core.ImageLoader; /** * 适配器 * Created by lizheng on 14/10/19. */ public class DemoAdapter extends RecyclerView.Adapter<DemoAdapter.DemoViewHolder> { String[] picUrls; public DemoAdapter(String[] picUrls) { this.picUrls = picUrls; } @Override public DemoViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) { // 加载数据item的布局,生成VH返回 View v = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.item_test, viewGroup, false); return new DemoViewHolder(v); } @Override public void onBindViewHolder(DemoViewHolder demoViewHolder, int i) { // 数据绑定 ImageLoader.getInstance().displayImage(picUrls[i], demoViewHolder.imavPic); demoViewHolder.tvUrl.setText(picUrls[i]); } @Override public int getItemCount() { // 返回数据有多少条 if (null == picUrls) { return 0; } return picUrls.length; } // 可复用的VH public static class DemoViewHolder extends RecyclerView.ViewHolder { // 大图 public ImageView imavPic; // 图片url public TextView tvUrl; public DemoViewHolder(View itemView) { super(itemView); imavPic = (ImageView) itemView.findViewById(R.id.imavPic); tvUrl = (TextView) itemView.findViewById(R.id.tvUrl); } } }
Activity
布局
<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=".MainActivity"> <View android:background="#FFFFFF" android:id="@+id/vTestPalette" android:layout_width="match_parent" android:layout_height="48dp" /> <android.support.v4.widget.SwipeRefreshLayout android:id="@+id/swipeLayout" android:layout_below="@id/vTestPalette" android:layout_width="match_parent" android:layout_height="match_parent"> <android.support.v7.widget.RecyclerView android:id="@+id/recyclerView" android:layout_width="match_parent" android:layout_height="match_parent" android:scrollbars="vertical" /> </android.support.v4.widget.SwipeRefreshLayout> </RelativeLayout>
item
布局
<?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="match_parent" android:layout_margin="5dp" android:orientation="vertical"> <ImageView android:id="@+id/imavPic" android:layout_width="match_parent" android:layout_height="150dp" android:scaleType="centerCrop" /> <TextView android:id="@+id/tvUrl" android:layout_width="match_parent" android:layout_height="wrap_content" android:lines="2" /> <View android:layout_width="match_parent" android:layout_height="2dp" /> </LinearLayout>
效果图
横向的ListView
实现横向的ListView
,修改线性布局管理器属性即可。
默认为
// 线性布局管理器 LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this);
修改为
// 线性布局管理器 LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this); linearLayoutManager.setOrientation(LinearLayoutManager.HORIZONTAL);
要想横向的效果好一些,需要对item的布局做一些小修改
<ImageView android:id="@+id/imavPic" android:layout_width="match_parent" android:layout_height="150dp" android:scaleType="centerCrop" />
改为
<ImageView android:id="@+id/imavPic" android:layout_width="150dp" android:layout_height="150dp" android:scaleType="centerCrop" />
效果图
GridView
实现此效果,更改布局管理器即可,并微调item的布局
// 线性布局管理器 LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this); linearLayoutManager.setOrientation(LinearLayoutManager.HORIZONTAL); // 设置布局管理器 recyclerView.setLayoutManager(linearLayoutManager);
改为
// 网格布局管理器 GridLayoutManager gridLayoutManager = new GridLayoutManager(this, 2); gridLayoutManager.setOrientation(LinearLayoutManager.VERTICAL); // 设置布局管理器 recyclerView.setLayoutManager(gridLayoutManager);
item布局中
<ImageView android:id="@+id/imavPic" android:layout_width="150dp" android:layout_height="150dp" android:scaleType="centerCrop" />
改为
<ImageView android:id="@+id/imavPic" android:layout_width="match_parent" android:layout_height="150dp" android:scaleType="centerCrop" />
通过可以修改方向、也可以修改行数。代码自己修改,下面直接显示效果图。注意修改方向要注意图片的宽度要适当,不建议使用match_parent
效果图1
效果图2
效果图3
瀑布流
实现瀑布流,修改布局管理器和item布局即可。
布局管理器
<span style="font-size:18px;">// 网格布局管理器 GridLayoutManager gridLayoutManager = new GridLayoutManager(this, 2); gridLayoutManager.setOrientation(LinearLayoutManager.VERTICAL); // 设置布局管理器 recyclerView.setLayoutManager(gridLayoutManager);</span>
改为
// 交错网格布局管理器 StaggeredGridLayoutManager staggeredGridLayoutManager = new StaggeredGridLayoutManager(2, LinearLayoutManager.VERTICAL); // 设置布局管理器 recyclerView.setLayoutManager(staggeredGridLayoutManager);
item布局
改为
<?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="match_parent" android:layout_margin="5dp" android:orientation="vertical"> <ImageView android:id="@+id/imavPic" android:layout_width="match_parent" android:layout_height="wrap_content" android:scaleType="centerCrop" /> <TextView android:id="@+id/tvUrl" android:layout_width="match_parent" android:layout_height="wrap_content" /> </LinearLayout>
同样可以修改为横向和行数,看效果即可。
效果图1
效果图2
效果图3
后记
RecylerView
作为新出现的组件。还有很多的问题和用法期待大家的发现。
已知问题
StaggeredGridLayoutManager
时图片会自动跳转- 没有可以直接使用的
onItemClickListener
- 没有直接使用的
headView
和footerView