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

.NET MAUI 7:如何为特殊元素设置字体及配置全局字体?

.NET MAUI 7 自定义字体覆盖系统元素方案

一、逐个元素的字体自定义方法

1. 对话框(Alert/Confirm)

MAUI原生Alert依赖系统Dialog,无法直接设置字体,需自定义实现:

  • 方案1:使用CommunityToolkit.Maui的Popup控件,完全自定义布局,直接给内部元素指定自定义字体:
    var popup = new Popup
    {
        Content = new VerticalStackLayout
        {
            Children = {
                new Label { Text = "提示内容", FontFamily = "YourCustomFont" },
                new Button { Text = "确认", FontFamily = "YourCustomFont" }
            }
        }
    };
    await PopupExtensions.ShowPopupAsync(this, popup);
    
  • 方案2:Android原生Renderer自定义AlertDialog:
    在Android项目中创建自定义Renderer:
    [assembly: ExportRenderer(typeof(Page), typeof(CustomAlertRenderer))]
    namespace YourApp.Droid.Renderers
    {
        public class CustomAlertRenderer : PageRenderer
        {
            public override async Task DisplayAlert(string title, string message, string cancel)
            {
                var alertDialog = new AlertDialog.Builder(Context)
                    .SetTitle(SetCustomFont(title))
                    .SetMessage(SetCustomFont(message))
                    .SetPositiveButton(cancel, (s, e) => { })
                    .Create();
                alertDialog.Show();
                // 给按钮设置字体
                alertDialog.GetButton((int)DialogButtonType.Positive).Typeface = Typeface.CreateFromAsset(Context.Assets, "YourCustomFont.ttf");
            }
    
            private SpannableString SetCustomFont(string text)
            {
                var spannable = new SpannableString(text);
                spannable.SetSpan(new CustomTypefaceSpan("YourCustomFont"), 0, text.Length, SpanTypes.ExclusiveExclusive);
                return spannable;
            }
        }
    
        public class CustomTypefaceSpan : TypefaceSpan
        {
            private readonly Typeface _typeface;
            public CustomTypefaceSpan(string fontName) : base(fontName)
            {
                _typeface = Typeface.CreateFromAsset(Android.App.Application.Context.Assets, $"{fontName}.ttf");
            }
    
            public override void UpdateDrawState(TextPaint ds)
            {
                ApplyCustomTypeface(ds, _typeface);
            }
    
            public override void UpdateMeasureState(TextPaint paint)
            {
                ApplyCustomTypeface(paint, _typeface);
            }
    
            private void ApplyCustomTypeface(TextPaint paint, Typeface typeface)
            {
                paint.SetTypeface(typeface);
            }
        }
    }
    

2. 日历控件(DatePicker/CalendarView)

针对原生DatePicker,Android端需自定义Renderer修改内部字体:

[assembly: ExportRenderer(typeof(DatePicker), typeof(CustomDatePickerRenderer))]
namespace YourApp.Droid.Renderers
{
    public class CustomDatePickerRenderer : DatePickerRenderer
    {
        protected override void OnElementChanged(ElementChangedEventArgs<DatePicker> e)
        {
            base.OnElementChanged(e);
            if (Control != null)
            {
                // 设置输入框字体
                Control.Typeface = Typeface.CreateFromAsset(Context.Assets, "YourCustomFont.ttf");
                // 弹出的日历控件字体
                var calendarView = new CalendarView(Context);
                calendarView.SetDateTextAppearance(Resource.Style.CustomCalendarText);
                calendarView.SetWeekDayTextAppearance(Resource.Style.CustomCalendarText);
            }
        }
    }
}

同时在Android项目的Resources/values/styles.xml中添加样式:

<style name="CustomCalendarText" parent="@android:style/TextAppearance.Medium">
    <item name="android:fontFamily">@font/yourcustomfont</item>
</style>

注意要将字体文件放在Resources/font目录下(需手动创建font文件夹)。

3. Flyout底部选项卡栏

如果是Shell的底部TabBar,Android端需自定义ShellRenderer修改TabLayout字体:

[assembly: ExportRenderer(typeof(AppShell), typeof(CustomShellRenderer))]
namespace YourApp.Droid.Renderers
{
    public class CustomShellRenderer : ShellRenderer
    {
        protected override IShellBottomNavViewAppearanceTracker CreateBottomNavViewAppearanceTracker(ShellItem shellItem)
        {
            return new CustomBottomNavViewAppearanceTracker();
        }

        private class CustomBottomNavViewAppearanceTracker : IShellBottomNavViewAppearanceTracker
        {
            public void Dispose() { }

            public void ResetAppearance(BottomNavigationView bottomView)
            {
                SetCustomFont(bottomView);
            }

            public void SetAppearance(BottomNavigationView bottomView, ShellAppearance appearance)
            {
                SetCustomFont(bottomView);
            }

            private void SetCustomFont(BottomNavigationView bottomView)
            {
                var typeface = Typeface.CreateFromAsset(Android.App.Application.Context.Assets, "YourCustomFont.ttf");
                foreach (var item in bottomView.Menu)
                {
                    var span = new SpannableString(item.TitleFormatted);
                    span.SetSpan(new CustomTypefaceSpan("YourCustomFont"), 0, span.Length(), SpanTypes.ExclusiveExclusive);
                    item.SetTitle(span);
                }
            }
        }
    }
}

4. 上下文菜单按钮(ContextMenu)

MAUI的ContextMenu菜单项可通过自定义MenuItem的Style来设置字体:
在Resources/Styles.xaml中定义全局MenuItem样式:

<Style TargetType="MenuItem">
    <Setter Property="FontFamily" Value="YourCustomFont" />
</Style>

如果是Android原生上下文菜单,需自定义Renderer:

[assembly: ExportRenderer(typeof(ContentPage), typeof(CustomContextMenuRenderer))]
namespace YourApp.Droid.Renderers
{
    public class CustomContextMenuRenderer : PageRenderer
    {
        public override void OnCreateContextMenu(IContextMenu menu, View v, IContextMenuContextMenuInfo menuInfo)
        {
            base.OnCreateContextMenu(menu, v, menuInfo);
            var typeface = Typeface.CreateFromAsset(Context.Assets, "YourCustomFont.ttf");
            for (int i = 0; i < menu.Size(); i++)
            {
                var item = menu.GetItem(i);
                var span = new SpannableString(item.TitleFormatted);
                span.SetSpan(new CustomTypefaceSpan("YourCustomFont"), 0, span.Length(), SpanTypes.ExclusiveExclusive);
                item.SetTitle(span);
            }
        }
    }
}

二、Android/iOS全局字体配置(支持覆盖)

Android端全局配置

  1. 将字体文件放入Resources/font目录,并重命名为小写(如yourcustomfont.ttf)
  2. 在Resources/values/styles.xml中修改AppTheme:
<style name="AppTheme" parent="Theme.MaterialComponents.DayNight.DarkActionBar">
    <item name="android:fontFamily">@font/yourcustomfont</item>
    <item name="fontFamily">@font/yourcustomfont</item>
    <!-- 针对不同控件的字体继承 -->
    <item name="android:textViewStyle">@style/CustomTextViewStyle</item>
    <item name="android:buttonStyle">@style/CustomButtonStyle</item>
</style>

<style name="CustomTextViewStyle" parent="@android:style/Widget.TextView">
    <item name="android:fontFamily">@font/yourcustomfont</item>
</style>

<style name="CustomButtonStyle" parent="@android:style/Widget.Button">
    <item name="android:fontFamily">@font/yourcustomfont</item>
</style>

这样系统默认控件会继承全局字体,MAUI中单独设置FontFamily的元素会覆盖全局配置。

iOS端全局配置

  1. 将字体文件添加到iOS项目,在Info.plist中添加UIAppFonts数组,包含字体文件名(如YourCustomFont.ttf)
  2. 在AppDelegate.cs的FinishedLaunching方法中设置全局字体:
public override bool FinishedLaunching(UIApplication app, NSDictionary options)
{
    Microsoft.Maui.Handlers.LabelHandler.Mapper.AppendToMapping("CustomFont", (handler, view) =>
    {
        if (view.FontFamily == null)
            handler.Controller.Font = UIFont.FromName("YourCustomFont", (nfloat)view.FontSize);
    });
    // 其他控件全局设置
    UILabel.Appearance.Font = UIFont.FromName("YourCustomFont", 14);
    UIButton.Appearance.TitleLabel.Font = UIFont.FromName("YourCustomFont", 14);
    return base.FinishedLaunching(app, options);
}

同样,MAUI元素单独设置FontFamily时会优先使用自定义值,覆盖全局配置。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.22 05:00:41