世間ではXamarin.Formsの 4.0プレビュー版が入手可能になっています。
https://blog.xamarin.com/xamarin-forms-4-0-feature-preview-an-entirely-new-point-of-collectionview/
その中で CollectionView
の機能更新があります。
中でも注目なのが CarouselView
の実装です。
昔 Xamarin.Forms.CarouselView
というライブラリがあったのですが、 .NET Standardに対応しておらず、
PCLプロジェクト非推奨な現在においては空前のカルーセルロストだったのですが、ようやく公式にお目見えです。
なお、若干のToDoコメントが見られるものの、既にコードが Xamarin.Forms 3.6 でも実装されているため、 安定版でもプレビュー機能を有効にすることにより動かすことが出来てしまいます。
それでは使い方を見ていきましょう。
CollectionView機能の有効化
MainActivity.cs
や AppDelegate.cs
の Xamarin.Forms 初期化のところに、以下の1行を挿入することで、 CollectionView
が有効になります。
global::Xamarin.Forms.Forms.SetFlags("CollectionView_Experimental"); // ←これを追加 global::Xamarin.Forms.Forms.Init(this, bundle);
どんなViewにするか
簡単に以下の様な仕様のようなViewを作りたいとします。
- キャラクター一覧をスワイプして見れる
- 遷移元によってビューに表示させる初期値が変化する
INavigationAware
のためにPrismを使う
Xamlの書き方
基本的に昔の Xamarin.Forms.CarouselView
と書き方は同じです。
記述例を以下に示します。
<?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:prism="clr-namespace:Prism.Mvvm;assembly=Prism.Forms" prism:ViewModelLocator.AutowireViewModel="True" x:Class="MyApp.Views.CharacterDetailPage" Title="プロフィール詳細" InitialIndex="{Binding SelectedCharacterIndex}" > <ContentPage.Content> <CarouselView x:Name="CV" ItemsSource="{Binding Characters}"> <CarouselView.ItemsLayout> <GridItemsLayout Orientation="Horizontal" SnapPointsType="MandatorySingle" SnapPointsAlignment="Center"/> </CarouselView.ItemsLayout> <CarouselView.ItemTemplate> <DataTemplate> <StackLayout> <Image Source="{Binding Image}" HorizontalOptions="FillAndExpand" HeightRequest="{Binding ImageHeight}" /> <Label Text="{Binding Name}" FontSize="Medium"/> <Label Text="{Binding Description}" FontSize="Medium" HorizontalOptions="Center"/> </StackLayout> </DataTemplate> </CarouselView.ItemTemplate> </CarouselView> </ContentPage.Content> </ContentPage>
ContentPageの InitialIndex
は、詳しくはViewのコードビハインド参照ですが、独自に追加したBindablePropertyです。
ここの設定のミソは、 GridItemsLayout
の各種設定です
属性 | 型 | 説明 |
---|---|---|
Orientation | Xamarin.Forms.Itemslayout.Orientation | スクロール方向を決める |
SnapPointsType | Xamarin.Forms.SnapPointsType | スクロールの張り付き方を決める。 MandatorySingle で単一ページにびしっと張り付き、 None だとスムーズにスクロールする |
SnapPointsAlignment | Xamarin.Forms.SnapPointsAlignment | スクロール張り付きの基準座標を決める。 Start , Center , End の中から決める |
コードビハインド(xaml.cs)
ここで書くコードは少ないですが、前述のBindablePropertyは追加したからには定義する必要があります。
CarouselViewをスクロールさせるメソッドは ScrollTo
です。
public partial class CharacterDetailPage : ContentPage { // BindablePropertyを定義する public static readonly BindableProperty InitialIndexProperty = BindableProperty.Create("InitialIndex", typeof(int), typeof(CharacterDetailPage), 0 , BindingMode.OneWay, null, OnInitialIndexPropertyChanged, null, null); private static void OnInitialIndexPropertyChanged(BindableObject bindable, object oldvalue, object newvalue) { var view = bindable as CharacterDetailPage; if (view == null || !(newvalue is int)) { return; } // CarouselViewをスクロールさせる view.CV.ScrollTo((int)newvalue, // Scroll先のIndex -1, // グループ(無い場合は-1) ScrollToPosition.Center, // スクロール位置の基準 false // スクロールアニメーションを行うか ); } public CharacterDetailPage() { InitializeComponent(); } }
ViewModel
ここはあまり説明が要らないかもしれません。
OnNavigatedTo
メソッドでデータを読み込んで初期値 _defaultIndex
を設定しています。
捕捉すると データはここに無いモデルからロードします。 初期値はPrismのナビゲーションで受け取ったパラメータから取得します。 それらの値は Viewにバインドされています。
public class CharacterDetailPageViewModel : BindableBase, INavigationAware { public static readonly string DefaultIndexKey = "SelectedId"; private ObservableCollection<Character> _characters; public ObservableCollection<Character> Characters { get { return _characters; } set { SetProperty(ref _characters, value); } } private int _selectedCharacterIndex; public int SelectedCharacterIndex { get { return _selectedCharacterIndex; } set { SetProperty(ref _selectedCharacterIndex, value); } } public CharacterDetailPage() { CharacterItems = new ObservableCollection<CharacterItem>(); } public void OnNavigatedFrom(INavigationParameters parameters) { } public void OnNavigatedTo(INavigationParameters parameters) { var _defaultIndex = parameters[DefaultIndexKey] as int?; if (_defaultIndex != null) { var _characters = TeamModel.loadCharacters(); // キャラクターの読み込み foreach (var _character in _characters) { CharacterItems.Add(_character); } SelectedCharacterItemIndex = _defaultIndex; } } public void OnNavigatingTo(INavigationParameters parameters) { } } public class Character { public string Name { get; set; } public string Description { get; set; } public ImageSource Image { get; set; } }
まとめ
- CollectionViewを使うにはネイティブのXamarin.Forms初期化部分に
global::Xamarin.Forms.Forms.SetFlags("CollectionView_Experimental");
を書く - スクロールの挙動は
CarouselView.ItemsLayout.GridItemsLayout
の属性で設定する - 移動したい場合は
CarouselView.ScrollTo()
メソッドを使う
これでカルーセルマスターだ!
参考
Xamarin.Forms CollectionView - Xamarin | Microsoft Docs
Xamarin.Forms/ItemsView.cs at 3.6.0 · xamarin/Xamarin.Forms · GitHub
Xamarin.Forms/CarouselView.cs at 3.6.0 · xamarin/Xamarin.Forms · GitHub