如何在MAUI中自定义底部标签页?解决安卓白层及iOS适配问题
问题描述
我创建了一个Tabbed Page,想要实现如图所示的底部标签栏样式:
我在Android端使用TabbedViewHandler实现了该效果,但自定义标签栏背后出现了多余的白色图层(如图),该如何移除?同时尚未找到适用于iOS端的类似解决方案。
我在Android端尝试的代码如下:
using Microsoft.Maui.Handlers; using Microsoft.Maui.Controls.Platform; using System.Reflection; #if ANDROID using static Android.Views.ViewGroup; using Android.Graphics.Drawables; using Google.Android.Material.BottomNavigation; using AndroidX.Core.View; #endif namespace Project.Views.Handlers { public class AndroidTabbedPageHandler : TabbedViewHandler { public AndroidTabbedPageHandler() { Mapper.AppendToMapping(nameof(CustomTabbedPage), (handler, view) => { #if ANDROID if (view is CustomTabbedPage) { FieldInfo tabbedPageManagerFieldInfo = typeof(TabbedPage).GetField("_tabbedPageManager", BindingFlags.NonPublic | BindingFlags.Instance); object tabbedPageManager = tabbedPageManagerFieldInfo?.GetValue(view); FieldInfo tabLayoutFieldInfo = tabbedPageManager?.GetType().GetField("_bottomNavigationView", BindingFlags.NonPublic | BindingFlags.Instance); BottomNavigationView bottomNavigationView = tabLayoutFieldInfo?.GetValue(tabbedPageManager) as BottomNavigationView; if (bottomNavigationView != null) { GradientDrawable drawable = new GradientDrawable(); drawable.SetShape(ShapeType.Rectangle); drawable.SetColor(Android.Graphics.Color.White); drawable.SetCornerRadius(40); MarginLayoutParams layoutParams = new(LayoutParams.WrapContent, LayoutParams.WrapContent); layoutParams.SetMargins(20, 0, 20, 40); bottomNavigationView.LayoutParameters = layoutParams; bottomNavigationView.LabelVisibilityMode = LabelVisibilityMode.LabelVisibilityUnlabeled; bottomNavigationView.SetElevation(12); ViewCompat.SetBackground(bottomNavigationView, drawable); } } #endif }); } } }
解决方案
Android端:移除多余白色图层
多余白色图层是TabbedPage底层父容器的默认背景,只需找到该容器并设置透明背景即可。同时建议避免反射访问私有字段(后续MAUI版本可能变更导致失效),改用更稳定的方式获取控件:
修改后的Android处理器代码:
using Microsoft.Maui.Handlers; using Microsoft.Maui.Controls.Platform; #if ANDROID using static Android.Views.ViewGroup; using Android.Graphics.Drawables; using Google.Android.Material.BottomNavigation; using AndroidX.Core.View; #endif namespace Project.Views.Handlers { public class AndroidTabbedPageHandler : TabbedViewHandler { public AndroidTabbedPageHandler() { Mapper.AppendToMapping(nameof(CustomTabbedPage), (handler, view) => { #if ANDROID if (view is CustomTabbedPage) { // 替代反射,直接从PlatformView获取BottomNavigationView var bottomNavigationView = PlatformView.FindViewById<BottomNavigationView>(Resource.Id.bottom_navigation); if (bottomNavigationView != null) { GradientDrawable drawable = new GradientDrawable(); drawable.SetShape(ShapeType.Rectangle); drawable.SetColor(Android.Graphics.Color.White); drawable.SetCornerRadius(40); MarginLayoutParams layoutParams = new(LayoutParams.WrapContent, LayoutParams.WrapContent); layoutParams.SetMargins(20, 0, 20, 40); bottomNavigationView.LayoutParameters = layoutParams; bottomNavigationView.LabelVisibilityMode = LabelVisibilityMode.LabelVisibilityUnlabeled; bottomNavigationView.SetElevation(12); ViewCompat.SetBackground(bottomNavigationView, drawable); // 获取父容器并设置透明背景,移除多余白色图层 var parentContainer = bottomNavigationView.Parent as ViewGroup; parentContainer?.SetBackgroundColor(Android.Graphics.Color.Transparent); } } #endif }); } } }
iOS端:实现圆角底部标签栏
iOS端通过自定义TabbedViewHandler修改UITabBar的样式,创建圆角背景并隐藏原生默认背景:
创建iOS平台处理器:
using Microsoft.Maui.Handlers; using UIKit; using CoreGraphics; #if IOS namespace Project.Views.Handlers { public class IOSTabbedPageHandler : TabbedViewHandler { protected override void ConnectHandler(UITabBarController platformView) { base.ConnectHandler(platformView); var tabBar = platformView.TabBar; // 隐藏原生背景和阴影 tabBar.ShadowImage = new UIImage(); tabBar.BackgroundImage = new UIImage(); // 创建带圆角和阴影的背景视图 var bgView = new UIView(new CGRect(20, 0, tabBar.Bounds.Width - 40, tabBar.Bounds.Height)) { BackgroundColor = UIColor.White, Layer = { CornerRadius = 40, MasksToBounds = false, ShadowColor = UIColor.Black.CGColor, ShadowOpacity = 0.3f, ShadowOffset = new CGSize(0, 2), ShadowRadius = 6 } }; // 将背景视图插入到最底层 tabBar.InsertSubview(bgView, 0); // 调整标签项布局,适配圆角区域 tabBar.InsetsContentViewsToSafeArea = false; tabBar.ItemPositioning = UITabBarItemPositioning.Fill; tabBar.ItemSpacing = 0; if (tabBar.Items != null) { tabBar.ItemWidth = (tabBar.Bounds.Width - 40) / tabBar.Items.Length; } } } } #endif
注册自定义处理器
在MauiProgram.cs中注册两个平台的处理器:
builder.ConfigureMauiHandlers(handlers => { #if ANDROID handlers.AddHandler<CustomTabbedPage, AndroidTabbedPageHandler>(); #endif #if IOS handlers.AddHandler<CustomTabbedPage, IOSTabbedPageHandler>(); #endif });
内容的提问来源于stack exchange,提问作者UmairAhmadK
相关产品推荐
相关产品推荐

