.NET 8 MAUI iOS:HideSoftInputOnTapped自定义Entry失效求助
问题解决:MAUI自定义Entry点击外部无法失焦隐藏键盘
问题描述
.NET 8 MAUI项目中,自定义Entry实现CustomRenderer后,即使页面设置HideSoftInputOnTapped="True",点击Entry外部区域时,Entry不会失去焦点,软键盘也无法隐藏。未使用CustomRenderer时该功能正常。
问题原因
自定义Renderer未正确同步MAUI元素与原生控件的焦点交互逻辑,MAUI默认的HideSoftInputOnTapped机制依赖原生控件响应失焦事件,而自定义Renderer的实现覆盖或缺失了这部分同步逻辑。
解决方案(iOS端)
修改iOS平台的CustomEntry_IOS渲染器,添加点击外部区域时让原生UITextField失焦的逻辑,同时同步MAUI元素的焦点状态。
修改后的CustomEntry_IOS代码
public class CustomEntry_IOS : EntryRenderer { public CustomEntry_IOS() { } protected override void OnElementChanged(ElementChangedEventArgs<Entry> e) { base.OnElementChanged(e); if (Control != null && e.NewElement != null) { CustomEntry entry = e.NewElement as CustomEntry; Control.ReturnKeyType = entry.ReturnKeyType.GetValueFromDescription(); Control.Placeholder = entry.Placeholder; // 添加点击外部失焦的手势监听 var tapGesture = new UITapGestureRecognizer(() => { Control.ResignFirstResponder(); // 让原生控件失焦,隐藏键盘 entry.Unfocus(); // 同步MAUI元素的焦点状态 }); // 将手势绑定到页面根视图 if (ViewController?.View != null) { ViewController.View.AddGestureRecognizer(tapGesture); } Control.ShouldReturn += (UITextField tf) => { entry.InvokeCompleted(); Control.ResignFirstResponder(); entry.Unfocus(); return true; }; SetKeybordType(entry.KeyBoardType); } } protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e) { try { base.OnElementPropertyChanged(sender, e); CustomEntry entry = sender as CustomEntry; if (e.PropertyName == CustomEntry.ReturnKeyPropertyName) { Control.ReturnKeyType = entry.ReturnKeyType.GetValueFromDescription(); } if (entry != null && entry.Keyboard == Keyboard.Numeric) { Control.KeyboardType = UIKeyboardType.PhonePad; } } catch (Exception ex) { // 保留原有日志逻辑 } } void SetKeybordType(Constants.eKeyboardTypes keyboardType) { switch (keyboardType) { case Constants.eKeyboardTypes.Default: Control.KeyboardType = UIKeyboardType.Default; break; case Constants.eKeyboardTypes.Email: Control.KeyboardType = UIKeyboardType.EmailAddress; break; case Constants.eKeyboardTypes.Numeric: Control.KeyboardType = UIKeyboardType.NumberPad; break; case Constants.eKeyboardTypes.NumericWithDecimal: Control.KeyboardType = UIKeyboardType.DecimalPad; break; case Constants.eKeyboardTypes.NumericWithMinusAndDigit: case Constants.eKeyboardTypes.NumericWithMinus: Control.KeyboardType = UIKeyboardType.NumbersAndPunctuation; break; default: Control.KeyboardType = UIKeyboardType.Default; break; } } }
关键修改点
- 在
OnElementChanged中添加UITapGestureRecognizer,绑定到页面根视图,点击时同时调用原生控件的ResignFirstResponder()和MAUI元素的Unfocus(),确保焦点状态同步。 - 在
ShouldReturn事件处理中,补充失焦和键盘隐藏逻辑,避免点击回车键后焦点未正确释放。
额外优化(Android端兼容)
如果需要兼容Android平台,可在Android的自定义Renderer中添加类似逻辑,通过触摸监听实现点击外部失焦:
Android端示例代码
public class CustomEntry_Android : EntryRenderer { private GestureDetector _gestureDetector; protected override void OnElementChanged(ElementChangedEventArgs<Entry> e) { base.OnElementChanged(e); if (Control != null && e.NewElement != null) { // 创建手势检测器 _gestureDetector = new GestureDetector(Context, new TapGestureListener(this)); // 给父视图添加触摸监听 if (ParentView != null) { ParentView.Touch += ParentView_Touch; } } } private void ParentView_Touch(object sender, TouchEventArgs e) { _gestureDetector.OnTouchEvent(e.Event); } private class TapGestureListener : GestureDetector.SimpleOnGestureListener { private readonly CustomEntry_Android _renderer; public TapGestureListener(CustomEntry_Android renderer) { _renderer = renderer; } public override bool OnSingleTapUp(MotionEvent e) { // 清除控件焦点并隐藏输入法 _renderer.Control.ClearFocus(); InputMethodManager imm = (InputMethodManager)_renderer.Context.GetSystemService(Context.InputMethodService); imm.HideSoftInputFromWindow(_renderer.Control.WindowToken, 0); (_renderer.Element as CustomEntry)?.Unfocus(); return base.OnSingleTapUp(e); } } protected override void Dispose(bool disposing) { if (disposing && ParentView != null) { ParentView.Touch -= ParentView_Touch; _gestureDetector?.Dispose(); } base.Dispose(disposing); } }
内容的提问来源于stack exchange,提问作者Anitha v
相关产品推荐
相关产品推荐

