shuhelohelo’s blog

Xamarin.Forms多めです.

Xamarin.Formsでオーバーレイしてダイアログ(というかページ)を表示させるにはどうしたらいいの?

例1:ライブラリ無しでピュアなXamarin.Formsで実現する

以下の例ではライブラリを使用せずに,PCLで,XamlC#で,ドノーマルのXamarin.Formsでカスタムダイアログ,カスタムメッセージボックスを表示させている.

winstongubantes.blogspot.com

手法としては,ダイアログを表示させたいページ内に,そのダイアログを記述したContentPageをロードしておく,というもの. ダイアログのContentPageを作成しておき,それをページ内のコンテンツとして読み込む.

        <Grid BackgroundColor="WhiteSmoke">
            <StackLayout VerticalOptions="Center">
                <Button x:Name="BtnShowDefaultDialog" 
                        Text="Show Dialog Without Content"
                        Command="{Binding Source={x:Reference PopUpDefaultDialog}, Path=ShowDialogCommand}"/>

            </StackLayout>

            <!--DIALOG DEFAULT-->
            <popupdialogs:PopupDialogView x:Name="PopUpDefaultDialog"
                                          DialogMargin="10, 60, 10, 60">
            </popupdialogs:PopupDialogView>

このContentPageの内容は,画面外に表示されていて見えないだけ.

ボタンが押されたときに,この画面外に表示されているコンテンツをアニメーションで画面内に移動させている.

ライブラリに頼らなくても実現できるので,ライブラリの更新が止まって困るということが無いのはメリット.

ライブラリを使って実現する.

カスタムメッセージボックス

以下の動画で紹介されている.

Rg.Plugin.Popupというライブラリを使っている.

f:id:shuhelohelo:20200306204158p:plain

もしMVVMフレームワークとしてPrismを使っている場合は,Prism.Plugin.Popupsというライブラリが提供されていて,Prismフレームワークの中でRg.Plugin.Popupが使える.

f:id:shuhelohelo:20200306203804p:plain

使い方は簡単で,ContentPageを新規作成し,ContentPage要素を以下のように変更する.

<rg:PopupPage
    x:Class="CustomMessageBox.MessageBox"
    xmlns="http://xamarin.com/schemas/2014/forms"
    xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
    xmlns:d="http://xamarin.com/schemas/2014/forms/design"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:rg="clr-namespace:Rg.Plugins.Popup.Pages;assembly=Rg.Plugins.Popup"
    mc:Ignorable="d">

このXaml側の変更に合わせてコードビハインド側も変更する. ContentPageクラスを継承していたところをPopupPageを継承するように変更する.

    public partial class MessageBox : PopupPage
    {
               ...
    }

このPopupPage要素の中に通常のContentPageと同じように表示したい見た目を作成する.これがダイアログとしてそのまま表示されることになる.

ダイアログを呼び出す側のページでは,C#コード側から以下のようにPopupPageを呼び出す.
例えば,ボタンのクリックイベントハンドラでダイアログを表示させる場合:
    private void Button_Clicked(object sender, EventArgs e)
    {
        var pop = new MessageBox();//PopupPageとして作成したクラスの名前
        App.Current.MainPage.Navigation.PushPopupAsync(pop, true);
    }

`PushPopupAsync`メソッドでPopupPageを表示させる.

現在表示中のPopupPageをNavigationスタックから取り除きたい場合は,`PopPopupAsync`メソッドを使う.

とても直感的に使える.

[f:id:shuhelohelo:20200306210053g:plain]


今回のソースコードはこちら.

[https://github.com/shuheydev/CustomMessageBox:embed:cite]



# 追加:Acr.UserDialogs

[https://www.mfractor.com/blogs/news/introduction-to-dialogs-in-xamarin-forms:embed:cite]

[https://devlinduldulao.pro/how-to-use-acr-userdialogs/:embed:cite]
    private async void ToolbarItem_Filter_Clicked(object sender, EventArgs e)
    {
        var choices = _viewModel.GroupedSessions.Select(g => $"{g.TrackID} : {g.TrackName}");

        string choice = await UserDialogs.Instance.ActionSheetAsync("Choose a track", "Cancel", null, CancellationToken.None, choices.ToArray());

        if(choice.Equals("Cancel"))
        {
            return;
        }

        var trackId = choice.Substring(0, 1);

        var group = _viewModel.GroupedSessions.FirstOrDefault(g => g.TrackID == trackId);
        var item = group.FirstOrDefault();

        HideSearchBox();
        CollectionsView_Sessions.ScrollTo(item, group, ScrollToPosition.Center, animate: false);
    }
[f:id:shuhelohelo:20200624233813p:plain]