アイキャッチ画像

【iOS】.NET MAUI ShellのTabBarでアイコンが大きくなる問題の解決方法

.NET MAUI ShellのTabBarでは、以下のようにタブにアイコンを表示することができます。

.NET MAUI ShellのTabBar

しかし、iOSでは以下のように大きくアイコンが表示されます。

iOSで.NET MAUI ShellのTabBarのアイコンが大きくなる現象

当記事ではこの解決方法を紹介していきます。

紹介環境

当記事は以下の環境で作成しています。

開発環境

  • Visual Studio 2022
  • .Net 8
  • iOS 17.4

TabBarについて

TabBarは以下のように記載することでタブ表示が行えます。

<?xml version="1.0" encoding="UTF-8" ?>
<Shell
    x:Class="SampleApp.AppShell"
    xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
    xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
    xmlns:pages="clr-namespace:SampleApp.Pages"
    Shell.FlyoutBehavior="Disabled"
    Title="SampleApp">
    <TabBar>
        <ShellContent Title="サンプル1" ContentTemplate="{DataTemplate pages:SamplePage1}" />
        <ShellContent Title="サンプル2" ContentTemplate="{DataTemplate pages:SamplePage2}" />
        <ShellContent Title="サンプル3" ContentTemplate="{DataTemplate pages:SamplePage3}" />
    </TabBar>
</Shell>

詳細は以下で紹介しています。良ければ参考にしてみてください。

iOSでアイコンが大きくなる現象について

iOSでTabBarのアイコンが大きくなる現象は、アイコンを画像で表示したときに発生します。原因は画像をリサイズさせずに表示するためです。

そのため、画像のサイズを 35×35 にすると以下のようにはみ出さずことなく表示できます。

.NET MAUI ShellのTabBarのアイコン画像を「35×35」にした結果

しかし、この方法ではアイコンがぼやけるため、当記事では別の方法を紹介します。

解決方法について

画像をそのまま表示されていることが問題なため、画像をリサイズできるようにして解決していきます。

手順1:ファイルを準備します

以下のようにファイルを準備します。

用意するファイル

手順2:ハンドラーをカスタムします

Shellのハンドラーをカスタムしていきます。

ShellRendererクラスをカスタムします

ShellのiOSのハンドラーはShellRendererクラスになります。そのShellRendererクラスをカスタムするために継承していきます。実装した内容は以下のようになります。

using Microsoft.Maui.Controls.Handlers.Compatibility;
using Microsoft.Maui.Controls.Platform.Compatibility;

namespace SampleApp.Platforms.iOS.Renderers;

// 名前空間はプロジェクトに合わせてください。
public class SampleShellRenderer : ShellRenderer
{
    protected override IShellSectionRenderer CreateShellSectionRenderer(ShellSection shellSection)
    {
        return new SampleShellSectionRenderer(this);
    }
}

ShellContentをカスタムするためにCreateShellSectionRendererメソッドを利用していきます。

ShellSectionRendererクラスをカスタムします

CreateShellSectionRendererメソッドで返却しているSampleShellSectionRendererクラスを作成していきます。

ShellContentをカスタムするためにShellSectionRendererクラスを継承します。実装した内容は以下のようになります。

using Microsoft.Maui.Controls.Platform.Compatibility;
using UIKit;

// 名前空間はプロジェクトに合わせてください。
namespace SampleApp.Platforms.iOS.Renderers;

public class SampleShellSectionRenderer : ShellSectionRenderer
{
    public SampleShellSectionRenderer(IShellContext context) : base(context)
    {
    }

    protected override void UpdateTabBarItem()
    {
        base.UpdateTabBarItem();
        if (TabBarItem.Image is not null)
            TabBarItem.ImageInsets = new UIEdgeInsets(35, 0, 35, 0);
    }
}

17行目の「new UIEdgeInsets(35, 0, 35, 0);」でアイコンのサイズを制御しています。例えば、「new UIEdgeInsets(45, 0, 45, 0);」にするとアイコンのサイズは小さくなります。

表示イメージは、以下のようになります。

new UIEdgeInsets(35, 0, 35, 0)にした時のイメージ
new UIEdgeInsets(35, 0, 35, 0)の場合
new UIEdgeInsets(45, 0, 45, 0)にした時のイメージ
new UIEdgeInsets(45, 0, 45, 0)の場合

手順3:カスタムしたハンドラーを登録します

カスタムしたハンドラー(SampleShellRenderer)を登録するために、MauiProgramクラスに以下のように実装していきます。

using Microsoft.Extensions.Logging;

#if IOS
using SampleApp.Platforms.iOS.Renderers;
#endif

namespace SampleApp;

public static class MauiProgram
{
    public static MauiApp CreateMauiApp()
    {
        var builder = MauiApp.CreateBuilder();
        builder
            .UseMauiApp<App>()
            .ConfigureFonts(fonts =>
            {
                fonts.AddFont("OpenSans-Regular.ttf", "OpenSansRegular");
                fonts.AddFont("OpenSans-Semibold.ttf", "OpenSansSemibold");
            })
        /* 追加します。======== */
            .ConfigureMauiHandlers((handlers) =>
            {
#if IOS
                handlers.AddHandler<Shell, SampleShellRenderer>();
#endif
            });
        /* ==================== */

#if DEBUG
        builder.Logging.AddDebug();
#endif

        return builder.Build();
    }
}

動作イメージ

動作イメージは以下のようになります。

動作イメージ

おわりに

モバイルアプリでタブページはよく利用するので、今回の現象はとても困りました。Xamarinではアセットカタログで解決できましたが、.Net MAUIでは存在していなかったのでカスタムレンダラで解決してみました。当記事が役に立つと幸いです。