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

.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;
        }
    }
}

关键修改点

  1. 在OnElementChanged中添加UITapGestureRecognizer,绑定到页面根视图,点击时同时调用原生控件的ResignFirstResponder()和MAUI元素的Unfocus(),确保焦点状态同步。
  2. 在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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.18 00:00:57