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

MAUI Android端无法通过Handler.PlatformView设置CustomEntry样式

Android端MAUI CustomEntry样式不生效的原因及解决办法

问题描述

我创建了CustomEntry自定义Entry控件,希望实现无下划线带边框的输入框,将Xamarin Render中的代码移植到MAUI的EntryHandler中,但Android端设置BackgroundColor、CornerRadius、BorderThickness、BorderColor等样式无效。相关代码如下:

CustomEntry定义

public class CustomEntry : Entry
{
 public static BindableProperty CornerRadiusProperty =
     BindableProperty.Create(nameof(CornerRadius), typeof(int), typeof(CustomEntry), 0);

 public static BindableProperty BorderThicknessProperty =
     BindableProperty.Create(nameof(BorderThickness), typeof(int), typeof(CustomEntry), 0);

      public static BindableProperty PaddingProperty =
      BindableProperty.Create(nameof(Padding), typeof(Thickness), typeof(CustomEntry), new Thickness(5));

 public static BindableProperty BorderColorProperty =
     BindableProperty.Create(nameof(BorderColor), typeof(Color), typeof(CustomEntry), Color.FromRgba(0, 0, 0, 0));

 public int CornerRadius
 {
     get => (int)GetValue(CornerRadiusProperty);
     set => SetValue(CornerRadiusProperty, value);
 }

 public int BorderThickness
 {
     get => (int)GetValue(BorderThicknessProperty);
     set => SetValue(BorderThicknessProperty, value);
 }
 public Color BorderColor
 {
     get => (Color)GetValue(BorderColorProperty);
     set => SetValue(BorderColorProperty, value);
 }
 /// <summary>
 /// This property cannot be changed at runtime in iOS.
 /// </summary>
 public Thickness Padding
 {
     get => (Thickness)GetValue(PaddingProperty);
     set => SetValue(PaddingProperty, value);
 }
}

XAML布局

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage
    x:Class="MauiApp.CustomEntry.MainPage"
    xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
    xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
    xmlns:controls="clr-namespace:MauiApp.CustomEntry.Controls"
    Shell.NavBarIsVisible="False">

    <ScrollView>
        <VerticalStackLayout Padding="30" Spacing="25">
            <controls:CustomEntry
                Padding="20,0,0,0"
                BackgroundColor="White"
                BorderColor="Blue"
                BorderThickness="2"
                CornerRadius="0"
                Placeholder="Insert a text"
                PlaceholderColor="Orange"
                Text="" />
        </VerticalStackLayout>
    </ScrollView>

</ContentPage>

MauiProgram中的Handler代码

public static class MauiProgram
{
    public static Microsoft.Maui.Hosting.MauiApp CreateMauiApp()
    {
        var builder = Microsoft.Maui.Hosting.MauiApp.CreateBuilder();
        builder
            .UseMauiApp<App>()
            .ConfigureFonts(fonts =>
            {
                fonts.AddFont("OpenSans-Regular.ttf", "OpenSansRegular");
                fonts.AddFont("OpenSans-Semibold.ttf", "OpenSansSemibold");
            });
        
       Microsoft.Maui.Handlers.EntryHandler.Mapper 
      .AppendToMapping("MyCustomization", (handler, view) =>
        {
      #if ANDROID
            
                if (view is MauiApp.CustomEntry.Controls.CustomEntry)
                {
                    var entry = (MauiApp.CustomEntry.Controls.CustomEntry)view;
                    handler.PlatformView.SetPadding(Convert.ToInt32(entry.Padding.Left), Convert.ToInt32(entry.Padding.Top), Convert.ToInt32(entry.Padding.Right), Convert.ToInt32(entry.Padding.Bottom));

                    var gd = new Android.Graphics.Drawables.GradientDrawable();
                    gd.SetColor(entry.BackgroundColor.ToAndroid());
                    gd.SetCornerRadius(entry.CornerRadius + 0f);
                    gd.SetStroke(entry.BorderThickness, entry.BorderColor.ToAndroid());
                    handler.PlatformView.SetBackground(gd);
                }

      #elif IOS
                if (view is CustomPaddingEntry)
                {
                    var entry = (CustomPaddingEntry)view;
                    handler.PlatformView.LeftView = new UIView(new CGRect(0, 0, entry.PaddingLeft, 1));
                    handler.PlatformView.LeftViewMode = UITextFieldViewMode.Always;
                    handler.PlatformView.RightView = new UIView(new CGRect(0, 0, entry.PaddingRight, 1));
                    handler.PlatformView.RightViewMode = UITextFieldViewMode.Always;
                    //TODO MAUI HANDLER - VERIFY IT
                    handler.PlatformView.BorderStyle = UIKit.UITextBorderStyle.None;
                }
            #endif
            });

                return builder.Build();
    }
}

原因分析

  1. 原生样式覆盖:Android原生EditText默认带有下划线和背景着色效果,你的自定义背景会被原生的BackgroundTintList覆盖。
  2. 单位未转换:MAUI的CornerRadius、Padding使用的是与设备无关的单位,直接赋值给Android控件会导致样式尺寸不符合预期。
  3. 属性变更无回调:自定义绑定属性未设置变更回调,动态修改属性时无法触发UI更新(初始化不生效主要是前两个原因)。

解决办法

修改Android端Handler代码

public static class MauiProgram
{
    public static Microsoft.Maui.Hosting.MauiApp CreateMauiApp()
    {
        var builder = Microsoft.Maui.Hosting.MauiApp.CreateBuilder();
        builder
            .UseMauiApp<App>()
            .ConfigureFonts(fonts =>
            {
                fonts.AddFont("OpenSans-Regular.ttf", "OpenSansRegular");
                fonts.AddFont("OpenSans-Semibold.ttf", "OpenSansSemibold");
            });
        
        Microsoft.Maui.Handlers.EntryHandler.Mapper 
            .AppendToMapping("MyCustomization", (handler, view) =>
            {
#if ANDROID
                if (view is MauiApp.CustomEntry.Controls.CustomEntry entry)
                {
                    // 禁用原生下划线和背景着色,避免覆盖自定义样式
                    handler.PlatformView.BackgroundTintList = Android.Content.Res.ColorStateList.ValueOf(Android.Graphics.Color.Transparent);
                    
                    // 将MAUI单位转换为Android像素
                    var metrics = Android.Content.Res.Resources.System.DisplayMetrics;
                    float cornerRadius = entry.CornerRadius * metrics.Density;
                    int paddingLeft = (int)(entry.Padding.Left * metrics.Density);
                    int paddingTop = (int)(entry.Padding.Top * metrics.Density);
                    int paddingRight = (int)(entry.Padding.Right * metrics.Density);
                    int paddingBottom = (int)(entry.Padding.Bottom * metrics.Density);

                    var gd = new Android.Graphics.Drawables.GradientDrawable();
                    gd.SetColor(entry.BackgroundColor.ToAndroid());
                    gd.SetCornerRadius(cornerRadius);
                    gd.SetStroke(entry.BorderThickness, entry.BorderColor.ToAndroid());
                    
                    handler.PlatformView.SetBackground(gd);
                    handler.PlatformView.SetPadding(paddingLeft, paddingTop, paddingRight, paddingBottom);
                }
#elif IOS
                if (view is MauiApp.CustomEntry.Controls.CustomEntry entry)
                {
                    handler.PlatformView.LeftView = new UIKit.UIView(new CoreGraphics.CGRect(0, 0, entry.Padding.Left, 1));
                    handler.PlatformView.LeftViewMode = UIKit.UITextFieldViewMode.Always;
                    handler.PlatformView.RightView = new UIKit.UIView(new CoreGraphics.CGRect(0, 0, entry.Padding.Right, 1));
                    handler.PlatformView.RightViewMode = UIKit.UITextFieldViewMode.Always;
                    handler.PlatformView.BorderStyle = UIKit.UITextBorderStyle.None;
                }
#endif
            });

        return builder.Build();
    }
}

给CustomEntry添加属性变更回调(可选,支持动态更新)

修改自定义绑定属性的创建代码,添加属性变更回调:

public class CustomEntry : Entry
{
    public static BindableProperty CornerRadiusProperty =
        BindableProperty.Create(nameof(CornerRadius), typeof(int), typeof(CustomEntry), 0, propertyChanged: OnCustomPropertyChanged);

    public static BindableProperty BorderThicknessProperty =
        BindableProperty.Create(nameof(BorderThickness), typeof(int), typeof(CustomEntry), 0, propertyChanged: OnCustomPropertyChanged);

    public static BindableProperty PaddingProperty =
        BindableProperty.Create(nameof(Padding), typeof(Thickness), typeof(CustomEntry), new Thickness(5), propertyChanged: OnCustomPropertyChanged);

    public static BindableProperty BorderColorProperty =
        BindableProperty.Create(nameof(BorderColor), typeof(Color), typeof(CustomEntry), Color.FromRgba(0,0,0,0), propertyChanged: OnCustomPropertyChanged);

    // ... 原有属性get/set代码不变 ...

    private static void OnCustomPropertyChanged(BindableObject bindable, object oldValue, object newValue)
    {
        if (bindable is CustomEntry entry && entry.Handler != null)
        {
            // 触发Handler更新所有自定义属性
            entry.Handler.UpdateValue(nameof(CornerRadius));
            entry.Handler.UpdateValue(nameof(BorderThickness));
            entry.Handler.UpdateValue(nameof(BorderColor));
            entry.Handler.UpdateValue(nameof(Padding));
        }
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.04 10:40:56