Xamarin.Forms 是Xamarin平台下的新框架,可以用一套UI代码,做多个平台的App,得到C#程序员们的喜爱,毕竟这代表着生产力大幅度提升。但是正如不完美的人类永远也做不成完美的事物来,xamarin.forms也有一些局限性(当然最新版已经支持在Forms中混合原生控件,解决了不少UI甚至UE上的问题)。例如,一个数据列表页面中,我们ListView很容易通过数据绑定手段实现列表,但是当数据足够多时就有问题了——通过webapi一次加载大量数据,既浪费流量也浪费时间,用户体验也很差(需要等待很久)。所以通常我们会让页面加载前面的一些数据,当用户将列表滑动到底部的时候再加载新的数据,这样循环往复可以不停的拉取新数据加载到列表中。很不幸,Xamarin.Forms的ListView控件默认并不直接支持这个功能。
控件的好处是复用,所以我们可以通过继承ListView,并稍微做一些改动调整来支持上滑到底部加载更多。代码如下:
public class InfiniteListView : ListView { public static readonly BindableProperty LoadMoreCommandProperty = BindableProperty.Create(nameof(LoadMoreCommand), typeof(ICommand), typeof(InfiniteListView)); public ICommand LoadMoreCommand { get { return (ICommand)GetValue(LoadMoreCommandProperty); } set { SetValue(LoadMoreCommandProperty, value); } } public InfiniteListView() { ItemAppearing += InfiniteListView_ItemAppearing; } private void InfiniteListView_ItemAppearing(object sender, ItemVisibilityEventArgs e) { var items = ItemsSource as IList; if (items != null && e.Item == items[items.Count - 1]) { if (LoadMoreCommand != null && LoadMoreCommand.CanExecute(null)) LoadMoreCommand.Execute(null); } } }
在XAML中调用这个控件的方式如下:
<?xml version="1.0" encoding="utf-8" ?> <ContentPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:Controls="clr-namespace:Codenutz.XF.Controls;assembly=Codenutz.XF.Controls.InfiniteListView" x:Class="Codenutz.XF.InfiniteListView.Shared.View.InfiniteListViewSampleView" Title="{Binding Title}"> <Controls:InfiniteListView ItemsSource="{Binding MarvelCharacters}" SelectedItem="{Binding SelectedCharacter}" LoadMoreCommand="{Binding LoadCharactersCommand}"> </Controls:InfiniteListView> </ContentPage>
原理很简单,就是当ListView的最后一个Item显示在屏幕上时,执行加载更多命令(LoadMoreCommand)。而我们在这个命令中获取下一页数据并填充到ListView的绑定中即可,尤其当你用MVVM模式开发App时,这会让你很爽。你试试看就知道了。
ListView控件在Xamarin.Forms的App中,还有不少局限,尤其是面对国内的复杂UI设计需求时,经常显得有点乏力,如何应对这些问题,我将在后续的文章中跟大家一起探讨。
特别声明:本文中的控件代码并非老衣原创,而是出自 http://www.codenutz.com/lac09-xamarin-forms-infinite-scrolling-listview/