如何在Xamarin.Forms的TabbedPage中使用iOS原生系统TabBar图标
Great question! Unfortunately, you can’t directly use UITabBarSystemItem values in Xamarin.Forms’ IconImageSource property out of the box. Xamarin.Forms is a cross-platform abstraction layer, so it doesn’t natively recognize iOS-specific UIKit enums. But we can easily solve this with a custom renderer and attached properties to bridge the gap between Forms and native iOS APIs. Here’s how to do it:
Step 1: Create an Attached Property in the Shared Project
First, we’ll define an attached property in our shared project to let us mark which system icon each page should use. This keeps our XAML clean and platform-agnostic.
Create a helper class (e.g., TabBarIconHelper.cs) in your shared project:
using Xamarin.Forms; namespace PhoneApp.Helpers { public static class TabBarIconHelper { // Define an enum that maps directly to iOS's UITabBarSystemItem values public enum TabBarSystemIcon { More = 0, Favorites = 1, Featured = 2, TopRated = 3, Recents = 4, Contacts = 5, History = 6, Bookmarks = 7, Search = 8, Downloads = 9, MostRecent = 10, MostViewed = 11 } // Attached property to store the selected system icon for each page public static readonly BindableProperty SystemIconProperty = BindableProperty.CreateAttached( "SystemIcon", typeof(TabBarSystemIcon), typeof(TabBarIconHelper), defaultValue: TabBarSystemIcon.More); public static void SetSystemIcon(BindableObject view, TabBarSystemIcon value) { view.SetValue(SystemIconProperty, value); } public static TabBarSystemIcon GetSystemIcon(BindableObject view) { return (TabBarSystemIcon)view.GetValue(SystemIconProperty); } } }
Step 2: Create a Custom Renderer for iOS
Next, we’ll build an iOS-specific renderer for your TabbedPage that reads the attached property and sets the native UITabBarItem icons using UITabBarSystemItem.
Create a renderer class (e.g., MainPageRenderer.cs) in your iOS project:
using UIKit; using Xamarin.Forms; using Xamarin.Forms.Platform.iOS; using PhoneApp.Helpers; using PhoneApp.Views; [assembly: ExportRenderer(typeof(MainPage), typeof(MainPageRenderer))] namespace PhoneApp.iOS.Renderers { public class MainPageRenderer : TabbedRenderer { protected override void OnElementChanged(VisualElementChangedEventArgs e) { base.OnElementChanged(e); // Exit early if the TabBar or page collection isn't ready if (e.NewElement == null || TabBar?.Items == null) return; var tabbedPage = (TabbedPage)e.NewElement; // Loop through each child page to set its system icon for (int i = 0; i < tabbedPage.Children.Count; i++) { var contentPage = tabbedPage.Children[i]; var selectedIcon = TabBarIconHelper.GetSystemIcon(contentPage); // Convert our custom enum to iOS's UITabBarSystemItem var uiKitIcon = (UITabBarSystemItem)(int)selectedIcon; if (TabBar.Items[i] is UITabBarItem tabItem) { // Set the system icon (iOS handles light/dark mode automatically) tabItem.Image = UITabBarSystemItemExtensions.GetImage(uiKitIcon); // Optional: Customize title colors for selected/unselected states tabItem.SetTitleTextAttributes( new UITextAttributes { ForegroundColor = UIColor.Gray }, UIControlState.Normal); tabItem.SetTitleTextAttributes( new UITextAttributes { ForegroundColor = UIColor.SystemBlue }, UIControlState.Selected); } } } } }
Step 3: Update Your XAML
Now go back to your MainPage.xaml and use the attached property to assign system icons to your pages. Don’t forget to add the namespace for your helper class:
<?xml version="1.0" encoding="utf-8" ?> <TabbedPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:views="clr-namespace:PhoneApp.Views" xmlns:helpers="clr-namespace:PhoneApp.Helpers" x:Class="PhoneApp.Views.MainPage"> <TabbedPage.Title> </TabbedPage.Title> <TabbedPage.Children> <views:FavouritesPage Title="Favourites" helpers:TabBarIconHelper.SystemIcon="Favorites"/> <views:RecentsPage Title="Recents" helpers:TabBarIconHelper.SystemIcon="Recents"/> <views:ContactsPage Title="Contacts" helpers:TabBarIconHelper.SystemIcon="Contacts"/> <views:KeypadPage Title="Keypad"/> <views:VoicemailPage Title="Voicemail"/> </TabbedPage.Children> </TabbedPage>
Key Notes
- This approach keeps your shared code clean and platform-agnostic—Android and other platforms won’t be affected.
- iOS automatically handles system icon styling for light/dark mode, so you don’t need to provide separate assets.
- For pages where you don’t set the
SystemIconattached property, you can still use the regularIconImageSourceproperty for custom icons.
内容的提问来源于stack exchange,提问作者Spirit_bird

