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

如何在.NET MAUI的iOS键盘工具栏添加导航Entry的上下箭头?

在MAUI iOS中实现键盘工具栏的上下箭头导航

要实现输入框间的导航,不能直接依赖原生的NextResponder——MAUI的视图层级和iOS原生响应链不对应,所以得自己维护输入框顺序并手动切换焦点,具体步骤如下:

1. 自定义Entry Handler(iOS平台)

在iOS项目中创建自定义的Entry Handler,负责构建带上下箭头的工具栏,并处理导航逻辑:

using Microsoft.Maui.Handlers;
using UIKit;
using Microsoft.Maui.Controls;

namespace YourAppNamespace.iOS.Handlers;

public class NavigableEntryHandler : EntryHandler
{
    protected override void ConnectHandler(UITextField platformView)
    {
        base.ConnectHandler(platformView);

        // 创建键盘工具栏
        var toolbar = new UIToolbar(new CoreGraphics.CGRect(0, 0, UIScreen.MainScreen.Bounds.Width, 44));
        toolbar.BarStyle = UIBarStyle.Default;

        // 上箭头按钮
        var prevBtn = new UIBarButtonItem(UIBarButtonSystemItem.Rewind, (s, e) => SwitchToPreviousEntry());
        // 下箭头按钮
        var nextBtn = new UIBarButtonItem(UIBarButtonSystemItem.FastForward, (s, e) => SwitchToNextEntry());
        // Done按钮
        var doneBtn = new UIBarButtonItem(UIBarButtonSystemItem.Done, (s, e) => platformView.EndEditing(true));

        // 占位空间,让按钮分布更合理
        var flexibleSpace = new UIBarButtonItem(UIBarButtonSystemItem.FlexibleSpace);
        toolbar.Items = new[] { prevBtn, flexibleSpace, nextBtn, flexibleSpace, doneBtn };

        platformView.InputAccessoryView = toolbar;
    }

    // 切换到上一个输入框
    private void SwitchToPreviousEntry()
    {
        var currentEntry = VirtualView as Entry;
        var page = currentEntry?.Parent as ContentPage;
        if (page == null) return;

        var allEntries = GetAllEntries(page.Content);
        var currentIndex = allEntries.IndexOf(currentEntry);

        if (currentIndex > 0)
        {
            allEntries[currentIndex - 1].Focus();
        }
    }

    // 切换到下一个输入框
    private void SwitchToNextEntry()
    {
        var currentEntry = VirtualView as Entry;
        var page = currentEntry?.Parent as ContentPage;
        if (page == null) return;

        var allEntries = GetAllEntries(page.Content);
        var currentIndex = allEntries.IndexOf(currentEntry);

        if (currentIndex < allEntries.Count - 1)
        {
            allEntries[currentIndex + 1].Focus();
        }
        else
        {
            // 最后一个输入框,直接关闭键盘
            (currentEntry.Handler.PlatformView as UITextField)?.EndEditing(true);
        }
    }

    // 递归获取页面所有Entry控件
    private List<Entry> GetAllEntries(VisualElement element)
    {
        var entries = new List<Entry>();

        if (element is Entry entry)
        {
            // 可添加过滤逻辑,比如跳过标记为无需导航的Entry
            // if (entry.ClassId != "SkipNavigation")
            entries.Add(entry);
        }

        if (element is Layout layout)
        {
            foreach (var child in layout.Children)
            {
                entries.AddRange(GetAllEntries(child));
            }
        }

        // 按控件Y轴坐标排序,确保从上到下的导航顺序
        return entries.OrderBy(e => e.Y).ToList();
    }
}

2. 注册自定义Handler

在MauiProgram.cs中注册这个Handler,让所有Entry使用自定义的iOS处理逻辑:

using YourAppNamespace.iOS.Handlers;

var builder = MauiApp.CreateBuilder();
builder
    .UseMauiApp<App>()
    .ConfigureMauiHandlers(handlers =>
    {
#if IOS
        handlers.AddHandler<Entry, NavigableEntryHandler>();
#endif
    });

关键说明

你之前用NextResponder.BecomeFirstResponder()无效的原因是:MAUI的Entry对应的原生UITextField,其NextResponder并不指向页面中的下一个Entry控件——MAUI的跨平台视图层级和iOS原生响应链是分离的,原生响应链无法识别MAUI的布局顺序,所以必须手动遍历获取输入框并切换焦点。

可选调整

  • 如果是横向布局的输入框,可修改排序逻辑为按X轴坐标排序
  • 若需排除某些Entry,可在GetAllEntries中添加判断(比如通过ClassId标记)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.28 04:36:32