Xamarin.FormsのSwipeViewでiOSのスワイプが使われているところのような動きにさせるには、というテーマでサンプルを作ってみた。
動作の内容
iOSでのスワイプ動作で想定しているのは「メール」のメールボックス内の動作のことで、次のものを実現させたかった。
- スワイプでオープンできるのは1項目のみ。
- スワイプオープン中の項目をタップしたらスワイプを閉じる。
- すでにオープン中のスワイプ項目があった場合、閉じる。
一応、CollectionViewのアイテムとしてSwipeViewを組み合わせただけでは、単純に複数項目がスワイプ可能で、またSwipeViewにGestureRecognizersを追加しそれに対してタップ時のCommandを設定した場合には、上のような動作にすることはできない。
CollectionViewにSelectionModeがあるのだが、これをSingleにしても1項目のみスワイプ可という機能は実現できなかった。
既存にあるか調査
まずググってみたところ、以下の3つの記事を見つけることができた。
上のはisEnableと関連付けて、1つでもスワイプオープンされたら、スワイプできないようにするというものみたいだ。
これだと、上の3が実現できなさそうだった。
これはSwipeViewを拡張してisOpenフィールドを追加して項目ごとにオープン・クローズを管理可能に変更、ViewModel側で制御するといった形だろうか。
拡張するというのとViewModel側でViewの動作制御をするような形なのがちょっともやもやする感じがする。
最後がこちらで、スワイプに関するイベントを受け取りView側のC#ソース内で制御するというもの。
これが一番いいように感じた。
実装
ベースとなるプロジェクトはVS2022のモバイルアプリ(Xamarin.Forms)というやつ。
このプロジェクトのItemsPageを修正したものでImagePage.xaml.cs、ImagePage.xaml、このページのViewModelのItemsVieModel.csが対象。
処理の概要は次のようになる。
- 現在Open中のSwipeViewをImagePage.xaml.csで管理する。
- SwipeEndedのオープンで、オープン中のSwipeViewを登録する。
クローズ処理で登録解除をする。 - SwipeStartedでオープン中のSwipeViewがあれば閉じる。
- SwipeItemのInvokedでオープン中のSwipeViewがあれば閉じる。
この部分閉じなくてもいいのかもしれないが、管理対象のSwipeViewの登録解除をするという意味合いも込めている。 - TapGestureRecognizerのTappedイベントで、現在オープン中のSwipeViewがあれば閉じる処理を行い、オープン中の物がなければタップ時のコマンドを呼び出す。
今回の実装では削除処理の呼び出しをしている。
以下がベースプロジェクトから変更した箇所を含むソースを抜粋したもの。
コメント