Xamarin FormsでCarouselViewControlを使う
1. はじめに
Xamarin Formsで以下のようなUIを作りたくて、Carouselコントロールについて あたふた したのでブログにメモっておきます。
2. いくつかのCarousel実装
久しぶりにXamarin Formsアプリ作り始めたのですが、そんな自分にとってはカルーセルがカオスに見えました。。。
どれ 使えばいいの?と・・・
ググったら公式のと非公式のと色々出てきまして、今回は「alexrainman/CarouselView」を使用しました。
一応公式の2つと合わせて以下の3つについて書いておこうと思います。
- Xamarin.Forms..CarouselPage
- Xamarin.Forms.CarouselView
- alexrainman/CarouselView
2.1. Xamarin.Forms.CarouselPage
Xamarin Formsの標準クラスです。
名前からも分かるようにページクラスです。
クラス図でいうと以下のような感じ。なので、ページ内の1要素として配置することは出来ないですね。
2.2. Xamarin.Forms.CarouselView
公式から出された奴ですね。
なんか一時期、CarouselPageはdeprecatedしてCarouselViewに移行する的な話を聞いた気がするのですが、Nugetしようとしたら、2016/7/28のプレリリースで止まっている。。。これはタヒってるのかな。。。
2.3. alexrainman/CarouselView
と、上記公式の2つが使えそうにないので、ググったら良さげなものがありました。
「alexrainman/CarouselView(https://github.com/alexrainman/CarouselView)」
こちらは以下のようにXamarin.Forms.Viewクラスの派生クラスとして実装されているのでPage内の1要素として利用することができます。
※「alexrainman/CarouselView」の実際に配置するコントロールクラス名は CarouselViewControlクラス になります。
3. 実装
では実装します。
(超簡単なサンプルだけど、alexrainman/CarouselViewを使った説明は日本語に少なげだったので、書いておこうと思いました。)
あと、一応 Prism の上で実装します。
3.1. ソリューション・プロジェクトの作成
Visual Studio 2017を起動します。
メニュー「ファイル→新規作成→プロジェクト」を選択。
ここでは、以下の設定で作成します。
プロジェクトテンプレート:「Prism→Xamarin.Forms→Prism Blank App(Xamarin.Forms)」
名前:UseAlexCarouselViewApp
3.2. Nugetパッケージの追加
UseAlexCarouselViewAppプロジェクト(Formsの共通実装のプロジェクト)のNugetパッケージマネージャを表示して、CarouselView.FormsPluginを検索し、インストールします(これが alexrainman/CarouselView になります)。
3.3. モデルクラスの追加
せっかくPrismを使用しているので、ページ情報を表すモデルクラスを追加します。
UseAlexCarouselViewApp/Models/PageInfo.cs を追加します。
// UseAlexCarouselViewApp\Models\PageInfo.cs using Xamarin.Forms; namespace UseAlexCarouselViewApp.Models { public class PageInfo { public string Name { get; set; } public Color ForeColor { get; set; } public Color BackColor { get; set; } } }
3.4. ViewModelにPageInfoコレクションを追加
デフォルトで作られたMainPageViewModelクラスにPageInfoコレクションプロパティを追加します。
後でPageに配置するCarouselViewControlのページにバインドするプロパティになります。
// UseAlexCarouselViewApp\ViewModels\MainPageViewModel.cs using System.Collections.ObjectModel; using Prism.Navigation; using Xamarin.Forms; using BlankApp6.ViewModels; namespace UseAlexCarouselViewApp.ViewModels { public class MainPageViewModel : ViewModelBase { // CarouselViewControlにバインドするページ情報コレクション public ObservableCollection<PageInfo> CarouselPageInfo { get; set; } public MainPageViewModel(INavigationService navigationService) : base (navigationService) { Title = "Main Page"; // コレクション初期化 this.CarouselPageInfo = new ObservableCollection<PageInfo> { new PageInfo { Name = "Page1", ForeColor=Color.Yellow, BackColor= Color.Red }, new PageInfo { Name = "Page2", ForeColor=Color.Black, BackColor= Color.Yellow }, new PageInfo { Name = "Page3", ForeColor=Color.Gold, BackColor= Color.Green } }; } } }
3.5. PageにCarouselViewControlを追加
MainPage.xamlにCarouselViewControlを配置して、MainViewModel.PageInfoをデータバインディングします。
UseAlexCarouselViewApp\Views\MainPage.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:cv="clr-namespace:CarouselView.FormsPlugin.Abstractions;assembly=CarouselView.FormsPlugin.Abstractions" x:Class="UseAlexCarouselViewApp.Views.MainPage" Title="{Binding Title}"> <StackLayout> <Label Text="Hello" /> <Editor BackgroundColor="Yellow" /> <cv:CarouselViewControl VerticalOptions="FillAndExpand" HorizontalOptions="FillAndExpand" Position="0" ShowIndicators="True" ShowArrows="True" ItemsSource="{Binding CarouselPageInfo}"> <cv:CarouselViewControl.ItemTemplate> <DataTemplate> <StackLayout VerticalOptions="FillAndExpand" HorizontalOptions="FillAndExpand" BackgroundColor="{Binding BackColor}"> <Label Text="{Binding Name}" TextColor="{Binding ForeColor}"/> </StackLayout> </DataTemplate> </cv:CarouselViewControl.ItemTemplate> </cv:CarouselViewControl> </StackLayout> </ContentPage>
ポイントは以下の通り。
- コントロールを使うのでページにnamespaceを追加する
以下により cvタグプレフィックス で CarouselViewControl が使えるようになります。
xmlns:cv="clr-namespace:CarouselView.FormsPlugin.Abstractions;assembly=CarouselView.FormsPlugin.Abstractions"
- CarouselViewControlを配置
親要素(ContentPage)で名前空間定義したタグプレフィックcvを使ってコントロールを配置定義しています。
ItemsSourceとかDataTemplate定義は普通のデータバインド対応コントロールと同じテーストです。
<cv:CarouselViewControl ...
- CarouselViewControlはView派生クラス
CarouselViewControlはView派生クラスなのでStackLayoutの子要素としてLabelやEditorと並べて配置可能です。
3.6. ViewRendererの初期化を追加
最後に重要な「ViewRendererの初期化」処理とiOS/androidそれぞれのプロジェクトに追加します。
androidは、UseAlexCarouselViewApp.Android\MainActivity.csに「CarouselViewRenderer.Init();」を追記します。
// UseAlexCarouselViewApp.Android\UseAlexCarouselViewApp.Android\MainActivity.cs ... using CarouselView.FormsPlugin.Android; // ←これも追記 ... namespace UseAlexCarouselViewApp.Droid { ... public class MainActivity : global::Xamarin.Forms.Platform.Android.FormsAppCompatActivity { ... global::Xamarin.Forms.Forms.Init(this, bundle); CarouselViewRenderer.Init(); // ←追記 ... } }
iOSは、UseAlexCarouselViewApp.iOS\AppDelegate.csに「CarouselViewRenderer.Init();」を追記します。
// UseAlexCarouselViewApp.OS\UseAlexCarouselViewApp.iOS\AppDelegate.cs ... using CarouselView.FormsPlugin.iOS; // ←これも追記 ... namespace UseAlexCarouselViewApp.iOS { ... public partial class AppDelegate : global::Xamarin.Forms.Platform.iOS.FormsApplicationDelegate { ... public override bool FinishedLaunching(UIApplication app, NSDictionary options) { global::Xamarin.Forms.Forms.Init(); CarouselViewRenderer.Init(); // ←追記 .. } } }
※ViewRenderer
ViewRendererは「Formsとネイティブコントロール要素との繋ぎ役」みたいな役割を持っています。
Forms上でのXXコントロールをandroidでは○○コントロールとして表示し、iOSでは△△コントロールとして表示する。また、各ネイティブで発生したアクション・イベントをFormsコントロールのイベントに結び付けるような、そんな役割を持っています。
4. ソースはココ
サンプル実装は↓↓↓↓↓に置いときました。