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

求助:基于MAUI Handler实现带左侧图标的自定义Entry控件

在MAUI Entry左侧添加图标(基于Handler实现)

1. 创建自定义Entry控件

先定义一个继承自Entry的自定义控件,添加用于绑定图标的属性:

public class IconEntry : Entry
{
    public static readonly BindableProperty IconSourceProperty =
        BindableProperty.Create(nameof(IconSource), typeof(ImageSource), typeof(IconEntry));

    public ImageSource IconSource
    {
        get => (ImageSource)GetValue(IconSourceProperty);
        set => SetValue(IconSourceProperty, value);
    }
}

2. 实现各平台的Handler逻辑

Android平台

在Platforms/Android目录下创建IconEntryHandler.cs:

using Android.Graphics.Drawables;
using Android.Widget;
using Microsoft.Maui.Platform;

namespace YourAppName.Platforms.Android;

public class IconEntryHandler : EntryHandler
{
    protected override void ConnectHandler(EditText platformView)
    {
        base.ConnectHandler(platformView);
        UpdateIcon();
    }

    protected override void DisconnectHandler(EditText platformView)
    {
        platformView.SetCompoundDrawables(null, null, null, null);
        base.DisconnectHandler(platformView);
    }

    protected override void OnElementPropertyChanged(System.ComponentModel.PropertyChangedEventArgs args)
    {
        base.OnElementPropertyChanged(args);
        if (args.PropertyName == IconEntry.IconSourceProperty.PropertyName)
        {
            UpdateIcon();
        }
    }

    private async void UpdateIcon()
    {
        if (VirtualView is not IconEntry iconEntry || PlatformView == null)
            return;

        var imageSource = iconEntry.IconSource;
        if (imageSource == null)
        {
            PlatformView.SetCompoundDrawables(null, null, null, null);
            return;
        }

        var imageService = MauiContext?.Services.GetRequiredService<IImageSourceServiceProvider>();
        if (imageService == null)
            return;

        var service = imageService.GetRequiredService<IImageSourceService>(imageSource);
        var drawable = await service.GetDrawableAsync(imageSource, MauiContext);
        
        // 调整图标大小和间距
        drawable.SetBounds(0, 0, 60, 60);
        PlatformView.SetCompoundDrawables(drawable, null, null, null);
        PlatformView.CompoundDrawablePadding = 16;
    }
}

iOS平台

在Platforms/iOS目录下创建IconEntryHandler.cs:

using UIKit;
using Microsoft.Maui.Platform;

namespace YourAppName.Platforms.iOS;

public class IconEntryHandler : EntryHandler
{
    private UIImageView? _iconImageView;

    protected override void ConnectHandler(UITextField platformView)
    {
        base.ConnectHandler(platformView);
        UpdateIcon();
    }

    protected override void DisconnectHandler(UITextField platformView)
    {
        _iconImageView?.RemoveFromSuperview();
        _iconImageView = null;
        platformView.LeftView = null;
        base.DisconnectHandler(platformView);
    }

    protected override void OnElementPropertyChanged(System.ComponentModel.PropertyChangedEventArgs args)
    {
        base.OnElementPropertyChanged(args);
        if (args.PropertyName == IconEntry.IconSourceProperty.PropertyName)
        {
            UpdateIcon();
        }
    }

    private async void UpdateIcon()
    {
        if (VirtualView is not IconEntry iconEntry || PlatformView == null)
            return;

        var imageSource = iconEntry.IconSource;
        if (imageSource == null)
        {
            PlatformView.LeftView = null;
            PlatformView.LeftViewMode = UITextFieldViewMode.Never;
            return;
        }

        var imageService = MauiContext?.Services.GetRequiredService<IImageSourceServiceProvider>();
        if (imageService == null)
            return;

        var service = imageService.GetRequiredService<IImageSourceService>(imageSource);
        var uiImage = await service.GetImageAsync(imageSource, MauiContext);
        
        _iconImageView?.RemoveFromSuperview();
        _iconImageView = new UIImageView(uiImage)
        {
            Frame = new CoreGraphics.CGRect(0, 0, 24, 24),
            ContentMode = UIViewContentMode.ScaleAspectFit
        };

        // 添加间距容器
        var paddingView = new UIView(new CoreGraphics.CGRect(0, 0, 40, 24));
        _iconImageView.Center = paddingView.Center;
        paddingView.AddSubview(_iconImageView);

        PlatformView.LeftView = paddingView;
        PlatformView.LeftViewMode = UITextFieldViewMode.Always;
    }
}

3. 注册Handler

在MauiProgram.cs中注册自定义Handler:

using YourAppName.Platforms.Android;
using YourAppName.Platforms.iOS;

namespace YourAppName;

public static class MauiProgram
{
    public static MauiApp CreateMauiApp()
    {
        var builder = MauiApp.CreateBuilder();
        builder
            .UseMauiApp<App>()
            .ConfigureFonts(fonts =>
            {
                fonts.AddFont("OpenSans-Regular.ttf", "OpenSansRegular");
                fonts.AddFont("OpenSans-Semibold.ttf", "OpenSansSemibold");
            });

        // 注册自定义Handler
#if ANDROID
        builder.ConfigureMauiHandlers(handlers =>
        {
            handlers.AddHandler<IconEntry, IconEntryHandler>();
        });
#elif IOS
        builder.ConfigureMauiHandlers(handlers =>
        {
            handlers.AddHandler<IconEntry, IconEntryHandler>();
        });
#endif

        return builder.Build();
    }
}

4. 在XAML中使用

在XAML页面中引用命名空间后,直接使用IconEntry:

<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:local="clr-namespace:YourAppName"
             x:Class="YourAppName.MainPage">

    <VerticalStackLayout Padding="20" Spacing="15">
        <local:IconEntry 
            Placeholder="请输入内容"
            IconSource="icon_email.png"
            BackgroundColor="#F5F5F5"
            CornerRadius="8"
            HeightRequest="45"/>
    </VerticalStackLayout>
</ContentPage>

注意事项

  • 确保图标文件已添加到各平台资源目录,并设置正确的生成操作(Android设为AndroidResource,iOS设为Resource)
  • 可根据需求调整图标大小、间距等参数,比如Android的drawable.SetBounds和CompoundDrawablePadding,iOS的Frame和容器宽度

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.23 12:12:35