You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Xamarin.iOS的AppShell中禁用对应路由的ShellContent按钮

问题描述
  • 我的AppShell包含3个ShellContent,在iOS平台出现异常:当处于某路由的二级或更深层级页面时,点击该路由对应的ShellContent按钮,会自动返回该路由的初始页面;此问题在UWP平台不存在。
  • 尝试通过设置IsEnabled="False"禁用当前路由的ShellContent按钮,但未生效。

AppShell布局截图:
AppShell

当前AppShell代码:

<TabBar>
    <ShellContent x:Name="BureauShell" Title="Bureau" ContentTemplate="{DataTemplate local:ViewLogin}" Icon="office-desk.png"/>
    <ShellContent x:Name="ServicesShell" Title="Services" ContentTemplate="{DataTemplate local:ViewMenu}" Icon="booking.png"/>
    <ShellContent x:Name="PiecesShell" Title="Batiment" ContentTemplate="{DataTemplate local:ViewChat}" Icon="building.png" />
</TabBar>
解决方案

方法一:拦截iOS默认Tab点击行为(无需禁用按钮)

iOS的Shell默认会在点击当前选中Tab时返回根页面,可通过自定义Shell渲染器拦截该行为:

  1. 在iOS项目中创建自定义渲染器:
using Microsoft.Maui.Controls.Handlers.Compatibility;
using Microsoft.Maui.Controls.Platform.Compatibility;
using UIKit;

namespace YourAppNamespace.iOS.Renderers;

public class CustomShellRenderer : ShellRenderer
{
    protected override IShellTabBarAppearanceTracker CreateTabBarAppearanceTracker()
    {
        return new CustomTabBarTracker();
    }
}

public class CustomTabBarTracker : ShellTabBarAppearanceTracker
{
    public override void UpdateLayout(UITabBarController controller)
    {
        base.UpdateLayout(controller);
        
        if (controller.TabBar.Items == null) return;
        
        foreach (var tabItem in controller.TabBar.Items)
        {
            tabItem.ValueChanged += (sender, e) =>
            {
                var currentItem = sender as UITabBarItem;
                var selectedIndex = Array.IndexOf(controller.TabBar.Items, currentItem);
                // 若点击的是当前已选中的Tab,阻止默认返回根页面行为
                if (controller.SelectedIndex == selectedIndex)
                {
                    e.Handled = true;
                }
            };
        }
    }
}
  1. 在iOS项目的MauiProgram.cs中注册渲染器:
builder.ConfigureMauiHandlers(handlers =>
{
#if IOS
    handlers.AddHandler(typeof(Shell), typeof(CustomShellRenderer));
#endif
});

方法二:动态禁用当前路由的ShellContent按钮

若需严格禁用按钮,需结合导航监听和渲染器同步状态:

  1. 在AppShell后台代码添加导航监听:
public partial class AppShell : Shell
{
    public AppShell()
    {
        InitializeComponent();
        Navigated += (_, __) => UpdateShellContentStates();
    }

    private void UpdateShellContentStates()
    {
        // 重置所有按钮状态
        BureauShell.IsEnabled = true;
        ServicesShell.IsEnabled = true;
        PiecesShell.IsEnabled = true;

        var currentRoute = CurrentState.Location.OriginalString;
        // 判断是否处于当前路由的深层页面,禁用对应按钮
        if (currentRoute.StartsWith("//Bureau") && currentRoute != "//Bureau")
            BureauShell.IsEnabled = false;
        else if (currentRoute.StartsWith("//Services") && currentRoute != "//Services")
            ServicesShell.IsEnabled = false;
        else if (currentRoute.StartsWith("//Batiment") && currentRoute != "//Batiment")
            PiecesShell.IsEnabled = false;
    }
}
  1. 在自定义渲染器中同步TabBarItem的启用状态:
    修改CustomTabBarTracker类,添加状态同步逻辑:
public override void UpdateAppearance(UITabBarController controller, ShellAppearance appearance)
{
    base.UpdateAppearance(controller, appearance);
    
    if (controller.TabBar.Items == null || Shell.Current is not AppShell appShell) return;
    
    controller.TabBar.Items[0].Enabled = appShell.BureauShell.IsEnabled;
    controller.TabBar.Items[1].Enabled = appShell.ServicesShell.IsEnabled;
    controller.TabBar.Items[2].Enabled = appShell.PiecesShell.IsEnabled;
}

方法三:通过Shell导航事件阻止返回

直接在AppShell中重写导航事件,拦截当前Tab的返回操作:

public partial class AppShell : Shell
{
    protected override void OnNavigating(ShellNavigatingEventArgs args)
    {
        base.OnNavigating(args);
        // 若点击Tab试图返回当前路由根页面,取消操作
        if (args.Source == ShellNavigationSource.TabBar 
            && args.Target.Location.OriginalString == CurrentState.Location.Root.OriginalString)
        {
            args.Cancel();
        }
    }
}

内容的提问来源于stack exchange,提问作者Antoine21000

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.08 02:34:52