.Net MAUI Shellは、Shell.OnBackButtonPressedでAndroidのバックボタンを無効にできます。しかし、iOSのスワイプバックは無効にできません。
当記事は、iOSのスワイプバックを無効にする方法を紹介していきます。
紹介環境
当記事は以下の環境で作成しています。
開発環境
- Visual Studio 2022
- .Net 8
iOSでスワイプバックを無効にする方法
iOSのスワイプバックは、UINavigationController.InteractivePopGestureRecognizer.Enabled(true:有効、false:無効)で制御できます。
以下の手順でUINavigationController.InteractivePopGestureRecognizer.Enabledを利用して、スワイプバックを無効にしていきます。
手順1:ShellSectionRendererをカスタマイズします
UINavigationController.InteractivePopGestureRecognizer.Enabledの制御は、ShellSectionRendererをカスタマイズして行います。
カスタマイズしたShellSectionRendererは、以下のようになります。
using Microsoft.Maui.Controls.Platform.Compatibility;
// 名前空間はプロジェクトに合わせてください。
namespace SampleApp.Platforms.iOS.Handlers;
public class CustomShellSectionRenderer : ShellSectionRenderer
{
private Page? _displayedPage;
public CustomShellSectionRenderer(IShellContext context) : base(context)
{
}
protected override void OnDisplayedPageChanged(Page page)
{
base.OnDisplayedPageChanged(page);
// 遷移時に適用します。
if (_displayedPage == page) return;
_displayedPage = page;
if (_displayedPage != null)
{
UpdateIsEnabledBackGesture();
}
}
private void UpdateIsEnabledBackGesture()
{
// スワイプバックを無効にします。
InteractivePopGestureRecognizer.Enabled = false;
}
}
遷移時に適用する必要がありますので、OnDisplayedPageChangedをオーバーライドしています。
手順2:ShellRendererをカスタマイズします
カスタマイズしたShellSectionRendererは、ShellRendererをカスタマイズして呼び出します。
カスタマイズしたShellRendererは、以下のようになります。
using Microsoft.Maui.Controls.Handlers.Compatibility;
using Microsoft.Maui.Controls.Platform.Compatibility;
// 名前空間はプロジェクトに合わせてください。
namespace SampleApp.Platforms.iOS.Handlers;
public class CustomShellRenderer : ShellRenderer
{
protected override IShellSectionRenderer CreateShellSectionRenderer(ShellSection shellSection)
{
// カスタマイズしたShellSectionRendererを呼び出します。
return new CustomShellSectionRenderer(this);
}
}
手順3:カスタマイズしたShellRendererを登録します
カスタマイズしたShellRendererは、アプリに登録する必要があります。
アプリの登録は以下のよう行います。
// 名前空間はプロジェクトに合わせてください。
namespace SampleApp;
public static class MauiProgram
{
public static MauiApp CreateMauiApp()
{
var builder = MauiApp.CreateBuilder();
builder
.UseMauiApp<App>()
// カスタマイズしたShellRendererを登録します。
.ConfigureMauiHandlers(handlers =>
{
#if IOS
handlers.AddHandler(typeof(AppShell), typeof(Platforms.iOS.Handlers.CustomShellRenderer));
#endif
});
return builder.Build();
}
}
これでiOSのスワイプバックが無効になります。
Androidのバックボタンと一緒に制御する方法
iOSでスワイプバックを無効にする方法を利用して、iOSのスワイプバックとAndroidのバックボタンを制御できる添付プロパティを作成していきます。
手順1:添付プロパティを準備します
iOSのスワイプバックとAndroidのバックボタンを制御するために、添付プロパティ(IsEnabledBackGesture)を以下のように準備します。
// 名前空間はプロジェクトに合わせてください。
namespace SampleApp.CustomController;
public class CustomPage
{
public static readonly BindableProperty IsEnabledBackGestureProperty =
BindableProperty.CreateAttached("IsEnabledBackGesture", typeof(bool), typeof(CustomPage), true);
public static bool GetIsEnabledBackGesture(BindableObject obj) => (bool)obj.GetValue(IsEnabledBackGestureProperty);
public static void SetIsEnabledBackGesture(BindableObject obj, bool value) => obj.SetValue(IsEnabledBackGestureProperty, value);
}
手順2:iOSのスワイプバックを制御します
iOSのスワイプバックを制御するためにCustomShellSectionRendererを以下のように修正します。
using Microsoft.Maui.Controls.Platform.Compatibility;
using SampleApp.CustomController;
// 名前空間はプロジェクトに合わせてください。
namespace SampleApp.Platforms.iOS.Handlers;
public class CustomShellSectionRenderer : ShellSectionRenderer
{
private Page? _displayedPage;
public CustomShellSectionRenderer(IShellContext context) : base(context)
{
}
protected override void OnDisplayedPageChanged(Page page)
{
base.OnDisplayedPageChanged(page);
// 遷移時に適用します。
if (_displayedPage == page) return;
_displayedPage = page;
if (_displayedPage != null)
{
UpdateIsEnabledBackGesture();
}
}
private void UpdateIsEnabledBackGesture()
{
// スワイプバックを制御します。
InteractivePopGestureRecognizer.Enabled = CustomPage.GetIsEnabledBackGesture(Shell.Current.CurrentPage);
}
}
手順3:Androidのバックボタンを制御します
Androidのバックボタンを制御するために、Shell.OnBackButtonPressedを以下のように利用していきます。
using SampleApp.CustomController;
// 名前空間はプロジェクトに合わせてください。
namespace SampleApp;
public partial class AppShell : Shell
{
public AppShell()
{
InitializeComponent();
Routing.RegisterRoute("SamplePage1", typeof(SamplePage1));
}
protected override bool OnBackButtonPressed()
{
// バックボタンを制御します。
if (CustomPage.GetIsEnabledBackGesture(CurrentPage))
{
return base.OnBackButtonPressed();
}
return true;
}
}
これでiOSのスワイプバックとAndroidのバックボタンを制御できるようになります。
利用方法してみる
作成したCustomPage.IsEnabledBackGestureは以下のように利用します。例では、iOSのスワイプバックとAndroidのバックボタンを無効にしています。
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage
xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:control="clr-namespace:SampleApp.CustomController"
control:CustomPage.IsEnabledBackGesture="False"
x:Class="SampleApp.SamplePage1"
Title="SamplePage1">
<VerticalStackLayout>
<Label Text="サンプルプログラム" VerticalOptions="Center" HorizontalOptions="Center" />
</VerticalStackLayout>
</ContentPage>
終わりに
Androidのバックボタンは簡単に無効できましたが、iOSのスワイプバックを無効にできなかったので作成してみました。当記事の内容が役に立てば幸いです。