求助:基于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
相关产品推荐
相关产品推荐

