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

自定义Editor的Completed事件触发异常,如何限制仅键盘Done触发?

这个问题我之前也碰到过!默认的Editor确实有这个坑——Completed事件会在失去焦点时也触发,根本分不清是用户按了键盘的Done/Next,还是只是点了别的地方。要解决这个问题,得靠自定义渲染器来区分两种场景,给你一步步说:

核心思路

我们要分别在Android和iOS平台上拦截原生控件的事件,只有当用户明确点击键盘的Done/Next键时,才触发Completed事件,而单纯的失去焦点(比如点击页面其他区域)则不触发。


步骤1:给你的CustomEditor添加自定义渲染器

假设你的CustomEditor已经继承自Xamarin.Forms的Editor,接下来分别处理两个平台:

Android平台实现

创建Android平台的渲染器,监听原生控件的EditorAction事件(这是键盘返回键触发的专属事件),同时屏蔽默认的焦点改变触发逻辑:

[assembly: ExportRenderer(typeof(CustomEditor), typeof(CustomEditorRenderer))]
namespace YourAppNamespace.Droid.Renderers
{
    public class CustomEditorRenderer : EditorRenderer
    {
        protected override void OnElementChanged(ElementChangedEventArgs<Editor> e)
        {
            base.OnElementChanged(e);

            if (Control != null)
            {
                // 移除默认的焦点改变事件,避免误触发Completed
                Control.FocusChange -= Control_FocusChange;
                // 监听键盘返回键的触发事件
                Control.EditorAction += Control_EditorAction;
            }
        }

        private void Control_EditorAction(object sender, TextView.EditorActionEventArgs e)
        {
            // 判断是否是Done或Next键触发的
            if (e.ActionId == ImeAction.Done || e.ActionId == ImeAction.Next)
            {
                // 手动触发CustomEditor的Completed事件
                ((IElementController)Element)?.SetValueFromRenderer(Editor.CompletedProperty, EventArgs.Empty);
                // 可选:让编辑器失去焦点
                Control.ClearFocus();
                e.Handled = true;
            }
        }

        // 空实现焦点改变事件,避免失去焦点时触发Completed
        private void Control_FocusChange(object sender, View.FocusChangeEventArgs e) { }
    }
}

iOS平台实现

iOS平台上,我们通过标记是否是Return键触发的失去焦点,来区分场景:

[assembly: ExportRenderer(typeof(CustomEditor), typeof(CustomEditorRenderer))]
namespace YourAppNamespace.iOS.Renderers
{
    public class CustomEditorRenderer : EditorRenderer
    {
        private bool _isReturnKeyPressed = false;

        protected override void OnElementChanged(ElementChangedEventArgs<Editor> e)
        {
            base.OnElementChanged(e);

            if (Control != null)
            {
                // 监听Return键点击事件
                Control.ShouldReturn += Control_ShouldReturn;
                // 监听编辑结束事件
                Control.DidEndEditing += Control_DidEndEditing;
            }
        }

        private bool Control_ShouldReturn(UITextField textField)
        {
            // 标记是Return键触发的
            _isReturnKeyPressed = true;
            // 触发Completed事件
            ((IElementController)Element)?.SetValueFromRenderer(Editor.CompletedProperty, EventArgs.Empty);
            // 收起键盘
            textField.ResignFirstResponder();
            return true;
        }

        private void Control_DidEndEditing(UITextField sender, UITextFieldDidEndEditingEventArgs args)
        {
            // 如果不是Return键导致的编辑结束,直接返回,不触发Completed
            if (!_isReturnKeyPressed) return;
            
            _isReturnKeyPressed = false;
            base.DidEndEditing(sender, args);
        }
    }
}

步骤2:使用修改后的CustomEditor

回到你的XAML代码,继续使用CustomEditor,此时Completed="OnDoneClicked"事件就只会在用户点击键盘的Done/Next键时触发,再也不会因为点击页面其他区域而误触发了!

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.26 07:03:03