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

.NET MAUI中如何禁用Editor键盘同时保留光标定位功能?

.NET MAUI Editor:隐藏键盘但保留光标可编辑功能

要实现点击Editor时仅允许调整光标位置、完全不弹出键盘,同时支持通过按钮编程更新内容,可通过自定义Handler(MAUI推荐的扩展方式)实现,以下分跨平台通用方案和Android特定方案说明:

一、跨平台通用方案(自定义Editor+平台Handler)

1. 创建自定义Editor控件

在共享项目中定义继承自Editor的自定义控件,添加绑定属性控制键盘禁用状态:

public class CustomEditor : Editor
{
    public static readonly BindableProperty DisableKeyboardProperty =
        BindableProperty.Create(
            nameof(DisableKeyboard), 
            typeof(bool), 
            typeof(CustomEditor), 
            false);

    public bool DisableKeyboard
    {
        get => (bool)GetValue(DisableKeyboardProperty);
        set => SetValue(DisableKeyboardProperty, value);
    }
}

2. Android平台Handler实现

在Platforms/Android/Handlers目录下创建CustomEditorHandler.cs,通过修改原生控件的输入类型阻止键盘弹出,同时保留焦点和光标定位能力:

using Android.Views.InputMethods;
using Microsoft.Maui.Handlers;
using Microsoft.Maui.Platform;

namespace YourAppNamespace.Platforms.Android.Handlers;

public class CustomEditorHandler : EditorHandler
{
    public CustomEditorHandler() : base(PropertyMapper)
    {
    }

    public static new IPropertyMapper<IEditor, IEditorHandler> PropertyMapper =
        new EditorMapper()
        {
            [nameof(CustomEditor.DisableKeyboard)] = MapDisableKeyboard
        };

    private static void MapDisableKeyboard(IEditorHandler handler, IEditor editor)
    {
        if (editor is CustomEditor customEditor && handler.PlatformView is MauiEditText editText)
        {
            if (customEditor.DisableKeyboard)
            {
                // 设置输入类型为Null,阻止系统弹出键盘
                editText.InputType = Android.Text.InputTypes.Null;
                // 确保控件可获取焦点、响应点击
                editText.Focusable = true;
                editText.FocusableInTouchMode = true;
                // 处理点击事件,手动定位光标到点击位置
                editText.Click += (s, e) =>
                {
                    editText.RequestFocus();
                    if (e is Android.Views.View.TouchEventArgs touchArgs && 
                        touchArgs.Event.Action == Android.Views.MotionEventActions.Up)
                    {
                        var offset = editText.GetOffsetForPosition(
                            touchArgs.Event.GetX(), 
                            touchArgs.Event.GetY());
                        editText.SetSelection(offset);
                    }
                };
            }
            else
            {
                // 恢复默认多行文本输入类型
                editText.InputType = Android.Text.InputTypes.TextMultiLine;
            }
        }
    }
}

3. iOS平台Handler实现(可选)

如果需要支持iOS,在Platforms/iOS/Handlers目录下创建CustomEditorHandler.cs,通过替换输入视图为空视图隐藏键盘:

using Microsoft.Maui.Handlers;
using UIKit;

namespace YourAppNamespace.Platforms.iOS.Handlers;

public class CustomEditorHandler : EditorHandler
{
    public CustomEditorHandler() : base(PropertyMapper)
    {
    }

    public static new IPropertyMapper<IEditor, IEditorHandler> PropertyMapper =
        new EditorMapper()
        {
            [nameof(CustomEditor.DisableKeyboard)] = MapDisableKeyboard
        };

    private static void MapDisableKeyboard(IEditorHandler handler, IEditor editor)
    {
        if (editor is CustomEditor customEditor && handler.PlatformView is UITextView textView)
        {
            // 禁用键盘时设置空输入视图
            textView.InputView = customEditor.DisableKeyboard ? new UIView() : null;
        }
    }
}

4. 注册Handler

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

builder.ConfigureMauiHandlers(handlers =>
{
#if ANDROID
    handlers.AddHandler<CustomEditor, Platforms.Android.Handlers.CustomEditorHandler>();
#endif
#if IOS
    handlers.AddHandler<CustomEditor, Platforms.iOS.Handlers.CustomEditorHandler>();
#endif
});

5. 在XAML中使用

引用自定义命名空间后,直接使用CustomEditor并开启DisableKeyboard:

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

    <StackLayout>
        <local:CustomEditor 
            DisableKeyboard="True" 
            Text="初始测试文本" 
            HeightRequest="150" />
        <!-- 添加按钮用于编程更新内容 -->
        <Button Text="插入文本" Clicked="InsertText_Clicked" />
    </StackLayout>
</ContentPage>

6. 编程更新内容示例

在代码后台实现按钮点击逻辑,可直接修改Text并维护光标位置:

private void InsertText_Clicked(object sender, EventArgs e)
{
    if (customEditor != null)
    {
        var cursorPos = customEditor.CursorPosition;
        customEditor.Text = customEditor.Text.Insert(cursorPos, "[插入的文本]");
        // 恢复光标到插入后的位置
        customEditor.CursorPosition = cursorPos + "[插入的文本]".Length;
    }
}

二、Android平台简易特定方案(无需自定义Handler)

如果仅需支持Android,可通过自定义渲染器(兼容MAUI)快速实现:

using Android.Content;
using Android.Views.InputMethods;
using Microsoft.Maui.Controls.Compatibility;
using Microsoft.Maui.Controls.Compatibility.Platform.Android;
using Microsoft.Maui.Controls.Platform;

[assembly: ExportRenderer(typeof(Editor), typeof(NoKeyboardEditorRenderer))]
namespace YourAppNamespace.Platforms.Android;

public class NoKeyboardEditorRenderer : EditorRenderer
{
    public NoKeyboardEditorRenderer(Context context) : base(context)
    {
    }

    protected override void OnElementChanged(ElementChangedEventArgs<Editor> e)
    {
        base.OnElementChanged(e);
        if (Control != null)
        {
            // 禁用键盘
            Control.InputType = Android.Text.InputTypes.Null;
            // 允许焦点和点击定位光标
            Control.Focusable = true;
            Control.FocusableInTouchMode = true;
            Control.Click += (s, args) =>
            {
                Control.RequestFocus();
                if (args is Android.Views.View.TouchEventArgs touchArgs)
                {
                    var offset = Control.GetOffsetForPosition(
                        touchArgs.Event.GetX(), 
                        touchArgs.Event.GetY());
                    Control.SetSelection(offset);
                }
            };
        }
    }
}

此方案会全局禁用所有Editor的键盘,若仅需针对特定Editor,可改为渲染自定义CustomEditor而非原生Editor。

说明

  • 你之前尝试的HideKeyboardAsync会导致键盘先弹出再隐藏,存在视觉闪烁;InputTransparent会让控件无法接收点击事件;HideSoftInputOnTapped仅在点击页面其他区域时隐藏键盘,均不符合需求。
  • 上述方案通过直接修改原生控件的输入属性,从根源阻止键盘弹出,同时保留了焦点和光标定位能力,完全支持通过按钮编程更新内容。

内容的提问来源于stack exchange,提问作者Nikola Savić

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.13 23:10:56