Xamarin.Forms : Sharpnadoでドラッグアンドドロップ可能なリストを作成するメモ
SharpnadoのGitHubリポジトリにあるサンプル動画でわかるように,このライブラリが提供する機能の一つとしてリスト状に表示した各アイテムをドラッグアンドドロップで位置を入れ替えることができるHorizontalListView
というコントロールがあります.
HorizontalListView
というコントロールですが,名前にHorizontalとついているので水平方向のリスト表示だけなのかと思いますが,縦方向も表示できます.
このメモは,このコントロールを使うための手順です.
Sharpnado.Presentation.Formsをインストールする
NugetでSharpnado.Presentation.Formsをインストールします.
プラットフォームごとの準備
Sharpnadoを使うために,各プラットフォームのプロジェクトでほんの少し準備があります.
Android
AndroidプロジェクトのMainActivity.cs
のOnCreate
メソッド内で,以下のようにSharpnadoInitializer.Initialize()
を追加します.
protected override void OnCreate(Bundle savedInstanceState) { TabLayoutResource = Resource.Layout.Tabbar; ToolbarResource = Resource.Layout.Toolbar; base.OnCreate(savedInstanceState); Xamarin.Essentials.Platform.Init(this, savedInstanceState); global::Xamarin.Forms.Forms.Init(this, savedInstanceState); SharpnadoInitializer.Initialize();//これ LoadApplication(new App()); }
iOS
iOSではAppDelegate.cs
のFinishedLaunching
メソッド内に以下のように追加します.
public override bool FinishedLaunching(UIApplication app, NSDictionary options) { global::Xamarin.Forms.Forms.Init(); SharpnadoInitializer.Initialize();//これ LoadApplication(new App()); return base.FinishedLaunching(app, options); }
ContentPage内での使い方
まずは名前空間を追加します.
<ContentPage ... xmlns:renderedViews="clr-namespace:Sharpnado.Presentation.Forms.RenderedViews;assembly=Sharpnado.Presentation.Forms" ... >
これでHorizontalListViewをContentPage内で使用する準備ができました.
HorizontalListViewを使う場合の基本的なVisual Treeの構成は以下のとおりです. 構造がわかりやすいように要素名だけにしています
<renderedViews:HorizontalListView> <renderedViews:HorizontalListView.ItemTemplate> <DataTemplate> <ViewCell> <!-- ここにアイテムの見た目を定義する --> </ViewCell> </DataTemplate> </renderedViews:HorizontalListView.ItemTemplate> </renderedViews:HorizontalListView>
これに様々なプロパティを追加し,アイテムの見た目の定義を入れると以下のようになります.
<renderedViews:HorizontalListView CollectionPadding="10" ColumnCount="1" EnableDragAndDrop="True" ItemHeight="160" ItemSpacing="30" ItemsSource="{Binding People}" ListLayout="Grid" VerticalOptions="FillAndExpand"> <renderedViews:HorizontalListView.ItemTemplate> <DataTemplate> <ViewCell> <Grid> <Frame Margin="10,0" BorderColor="Green" HasShadow="True"> <StackLayout Orientation="Horizontal"> <Image Aspect="AspectFill" Source="{Binding ImageSrc}" WidthRequest="100" /> <Label Margin="5" FontSize="Large" Text="{Binding Name}" /> </StackLayout> </Frame> </Grid> </ViewCell> </DataTemplate> </renderedViews:HorizontalListView.ItemTemplate> </renderedViews:HorizontalListView>
この状態で実行すると,以下のようにアイテムをドラッグアンドドロップで入れ替えることができます.
HorizontalListViewでデータを表示するために最低限必要なプロパティは以下のとおりです.(ItemsSourceは前提として)
もう一つ前提として,このHorizontalListViewは名前のとおり,デフォルトではHorizontalなリストです.
- ColumnCount
- 画面の幅にいくつのアイテムが収まるように表示するかを指定する.なので,少なくとも
1
以上が指定されていないと,何も表示されないので注意.
- 画面の幅にいくつのアイテムが収まるように表示するかを指定する.なので,少なくとも
以下はColumnCount="2"
の場合
- ItemHeight
- 名前のとおり,アイテムの高さを指定します.これを指定しないと,
ListLayout="Grid"
としたときに表示されません.
- 名前のとおり,アイテムの高さを指定します.これを指定しないと,
- ListLayout
- Linear 横1列の表示(デフォルト)
- Carousel 1画面に1アイテム
- Grid 格子状に上から下へ.列数は
ColumnCount
で指定. - EnableDragAndDrop ドラッグアンドドロップを有効にする
ところで,縦並びの一般的なListViewのような表示をするにはどうしたらよいかというと,ColumnCount="1"
,ListLayout="Grid"
という設定をすれば以下のようにオーソドックスな見た目になります.
ColumnCount="2"
,ListLayout="Grid"
という設定にすれば,以下のように2列の格子状に表示されます.
もちろん,この状態でドラッグアンドドロップできます.
ドラッグアンドドロップ中の見た目を変える
ここまでで素晴らしく便利なのですが,ViewCell
をDraggableViewCell
に変更すると,更に便利になります.
このコントロールはアイテムがドラッグアンドドロップ中かを示すIsDragAndDropping
というプロパティを持っているので,それをDataTrigger
で拾うことで,ドラッグアンドドロップ中の見た目を変更することができます.
<renderedViews:HorizontalListView ColumnCount="2" EnableDragAndDrop="True" ItemHeight="160" ItemsSource="{Binding People}" ListLayout="Grid"> <renderedViews:HorizontalListView.ItemTemplate> <DataTemplate> <renderedViews:DraggableViewCell x:Name="DraggableViewCell" IsDraggable="True"> <Grid> <Frame Margin="10,0" BorderColor="Green" HasShadow="True"> <Frame.Triggers> <DataTrigger Binding="{Binding Source={x:Reference DraggableViewCell}, Path=IsDragAndDropping}" TargetType="Frame" Value="True"> <Setter Property="BackgroundColor" Value="LightPink" /> <Setter Property="ScaleX" Value="1.05" /> </DataTrigger> </Frame.Triggers> <StackLayout Orientation="Horizontal"> <Image Aspect="AspectFill" Source="{Binding ImageSrc}" WidthRequest="100" /> <Label Margin="5" FontSize="Large" Text="{Binding Name}" /> </StackLayout> </Frame> </Grid> </renderedViews:DraggableViewCell> </DataTemplate> </renderedViews:HorizontalListView.ItemTemplate> </renderedViews:HorizontalListView>