自定义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
相关产品推荐
相关产品推荐

