近日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
android-sdk/extras/android/m2repository/com/android/support/recyclerview-v7
android-sdk/extras/android/support/v7/recyclerview
RecylerView
怎么引用<span style="font-size:18px;">dependencies { compile 'com.android.support:recyclerview-v7:21.0.0' }</span>
在此推荐使用Android Studio
开发Android项目
以下猜测可以使用,没有经过测试。
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
瀑布流
实现瀑布流,修改布局管理器和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);
改为
<?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>
同样可以修改为横向和行数,看效果即可。
RecylerView
作为新出现的组件。还有很多的问题和用法期待大家的发现。
StaggeredGridLayoutManager
时图片会自动跳转onItemClickListener
headView
和footerView