分类:C#、Android、VS2015;
创建日期:2016-02-19
一、简介
滚动视图(RecyclerView)的用法与布局控件的用法类似,唯一不同的是,所有布局控件中都可以包含多个组件,而滚动视图里只能包含一个组件。换言之,滚动视图就是一个专门的容器,这个容器里面可以包含一个大于屏幕宽度(或高度)的组件,你可以采用拖拽的方式来观察它包含的内容。
不过,话又说回来,如果滚动视图包含的这个组件是一个布局容器,容器内仍然可以包含多个组件。
1、需要安装Xamarin.Android.Support.v7.RecyclerView软件包
RecyclerView是由Android Support v7支持库提供的,用C#编写Android应用程序时,要使用RecyclerView,项目中必须包括Xamarin.Android.Support.v7.RecyclerView软件包。
软件包的具体添加办法见10.2节的介绍。
2、RecyclerView和ListView的对比
可将RecyclerView看作是替换ListView和GridView的新控件,RecyclerView的作用也是为了在小窗口内显示较大的数据集,但RecyclerView提供了更多的版式选项,以及对于大型集合的更好的优化处理。
ListView和RecyclerView的重要差异如下:
- 由于RecyclerView内置了动画处理,因此其用法比ListView复杂,需要编写的代码也较多。
- RecyclerView不提供预定义的适配器,必须自己去实现访问数据源的适配器代码。而ListView和GridView都包含了预定义的适配器。
- RecyclerView不提供项的单击事件,而是由助手类处理包含项的单击事件。而ListView则提供了项的click事件。
- RecyclerView通过滚动项增强了性能,它通过持续视图模式消除了不必要的布局资源查找。而在ListView中该模式是可选项。
- RecyclerView是基于模块化的设计思想来实现的,这使它更容易被定制。例如,无需对布局进行大量的代码更改就可以将其插入到应用程序中。而ListView的结构相对来说比较单一。
二、示例—ch1003RecyclerViewDemo
本节示例使用RecyclerView显示大量照片(32张),目的是为了测试其滚动性能,每个照片都用卡片视图来构造。
注意:本示例需要安装Xamarin.Android.Support.v7.RecyclerView软件包。具体安装办法见10.2节的介绍。
1、运行效果
2、设计步骤
(1)添加ch1003_PhotoCardView.axml文件
在layout文件夹下添加该文件。
<?xml version="1.0" encoding="utf-8"?> <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:card_view="http://schemas.android.com/apk/res-auto" android:layout_width="fill_parent" android:layout_height="wrap_content"> <android.support.v7.widget.CardView android:layout_width="match_parent" android:layout_height="wrap_content" card_view:cardElevation="4dp" card_view:cardUseCompatPadding="true" card_view:cardCornerRadius="7dp"> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical" android:padding="8dp"> <ImageView android:layout_width="match_parent" android:layout_height="wrap_content" android:id="@+id/imageView" android:scaleType="centerCrop" /> <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:textAppearance="?android:attr/textAppearanceMedium" android:textColor="#333333" android:text="Caption" android:id="@+id/textView" android:gravity="center_horizontal" /> </LinearLayout> </android.support.v7.widget.CardView> </FrameLayout>
(2)添加ch1003_RecyclerViewDemo.axml文件
在layout文件夹下添加该文件。
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent"> <Button android:id="@+id/btnRandPick" android:layout_width="wrap_content" android:layout_height="wrap_content" android:gravity="center_horizontal" android:textAppearance="?android:attr/textAppearanceLarge" android:text="随机挑选一张照片和首张交换" android:layout_gravity="center_horizontal" /> <android.support.v7.widget.RecyclerView android:id="@+id/recyclerView" android:scrollbars="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent" /> </LinearLayout>
(3)添加ch1003RecyclerViewDemo.cs文件
在SrcDemos文件夹下添加该文件。
using System; using Android.App; using Android.OS; using Android.Views; using Android.Widget; using Android.Support.V7.Widget; namespace MyDemos.SrcDemos { [Activity(Label = "【例10-3】滚动视图基本用法")] public class ch1003RecyclerViewDemo : Activity { RecyclerView.LayoutManager m; protected override void OnCreate(Bundle savedInstanceState) { base.OnCreate(savedInstanceState); var mPhotoAlbum = new PhotoAlbum(); SetContentView(Resource.Layout.ch1003_RecyclerViewDemo); var mRecyclerView = FindViewById<RecyclerView>(Resource.Id.recyclerView); // 必须为滚动视图创建一个布局管理器,它默认不创建 //方式1:纵向滚动 m = new LinearLayoutManager(this); //方式2:横向滚动,每屏2张图(2行) // m = new GridLayoutManager(this, 2, GridLayoutManager.Horizontal, false); mRecyclerView.SetLayoutManager(m); // 必须为RecyclerView创建一个适配器,没有适配器它什么都干不了 var mAdapter = new PhotoAlbumAdapter(mPhotoAlbum); mAdapter.ItemClick += (object sender, int position) => { int n = position + 1; Toast.MakeText(this, "这是第" + n + "张照片", ToastLength.Short).Show(); }; mRecyclerView.SetAdapter(mAdapter); Button randomPickBtn = FindViewById<Button>(Resource.Id.btnRandPick); randomPickBtn.Click += delegate { if (mPhotoAlbum != null) { int idx = mPhotoAlbum.RandomSwapTop(); mAdapter.NotifyItemChanged(0); mAdapter.NotifyItemChanged(idx); } }; } } public class Photo { public int PhotoID { get; set; } public string Caption { get; set; } } public class PhotoAlbum { private static int[] a = { Resource.Drawable.ch05sample_0, Resource.Drawable.ch05sample_1, Resource.Drawable.ch05sample_2, Resource.Drawable.ch05sample_3, Resource.Drawable.ch05sample_4, Resource.Drawable.ch05sample_5, Resource.Drawable.ch05sample_6, Resource.Drawable.ch05sample_7 }; private static Photo[] photos; private Random r = new Random(); public PhotoAlbum() { //模拟填充大量图片(此处填了32个)来观察滚动视图的性能 photos = new Photo[32]; for (int i = 0; i < photos.Length; i++) { int n = i % a.Length; photos[i] = new Photo { PhotoID = a[n], Caption = "小狗" + (i + 1) }; } } public int NumPhotos { get { return photos.Length; } } public Photo this[int i] { get { return photos[i]; } } // 随机挑选一张照片与最顶部的那张照片交换 public int RandomSwapTop() { Photo tmpPhoto = photos[0]; int rnd = r.Next(1, photos.Length); photos[0] = photos[rnd]; photos[rnd] = tmpPhoto; return rnd; } } public class PhotoViewHolder : RecyclerView.ViewHolder { public ImageView image { get; private set; } public TextView caption { get; private set; } public PhotoViewHolder(View itemView, Action<int> listener) : base(itemView) { image = itemView.FindViewById<ImageView>(Resource.Id.imageView); caption = itemView.FindViewById<TextView>(Resource.Id.textView); itemView.Click += (sender, e) => listener(base.AdapterPosition); } } public class PhotoAlbumAdapter : RecyclerView.Adapter { public event EventHandler<int> ItemClick; public PhotoAlbum myPhotoAlbum { get; set; } public override int ItemCount { get { return myPhotoAlbum.NumPhotos; } } public PhotoAlbumAdapter(PhotoAlbum photoAlbum) { myPhotoAlbum = photoAlbum; } public override void OnBindViewHolder(RecyclerView.ViewHolder holder, int position) { PhotoViewHolder vh = holder as PhotoViewHolder; vh.image.SetImageResource(myPhotoAlbum[position].PhotoID); vh.caption.Text = myPhotoAlbum[position].Caption; } public override RecyclerView.ViewHolder OnCreateViewHolder(ViewGroup parent, int viewType) { View itemView = LayoutInflater.From(parent.Context) .Inflate(Resource.Layout.ch1003_PhotoCardView, parent, false); PhotoViewHolder vh = new PhotoViewHolder(itemView, OnClick); return vh; } void OnClick(int position) { if (ItemClick != null) ItemClick(this, position); } } }