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

XF项目Android端24小时TimePicker聚焦/失焦事件未触发求助

解决Xamarin.Forms Android端24小时TimePicker焦点事件不触发的问题

我之前在做Xamarin.Forms项目的时候刚好碰到过一模一样的问题!当时折腾了好一阵才找到靠谱的解决办法,分享给你参考下:

问题根源

默认的Android TimePicker渲染器在切换到24小时模式后,原生控件的焦点事件没有正确映射到XF的Focused/Unfocused事件上,尤其是当我们自定义TimePickerDialog来实现24小时选择时,Dialog关闭后不会自动触发Unfocus事件。

具体解决方案

1. 自定义Android渲染器

创建一个继承自TimePickerRenderer的自定义渲染器,手动处理原生控件的焦点事件,并将其映射到XF控件的事件上:

[assembly: ExportRenderer(typeof(TimePicker), typeof(CustomTimePickerRenderer))]
namespace YourApp.Droid.Renderers
{
    public class CustomTimePickerRenderer : TimePickerRenderer
    {
        protected override void OnElementChanged(ElementChangedEventArgs<TimePicker> e)
        {
            base.OnElementChanged(e);

            if (Control != null)
            {
                // 订阅原生EditText的焦点变化事件
                Control.FocusChange += OnControlFocusChanged;
                // 设置24小时输入模式
                Control.InputType = Android.Text.InputTypes.ClassTime | Android.Text.InputTypes.TimeFlag24Hour;
                
                // 自定义TimePickerDialog实现24小时选择
                Control.Click += (sender, args) =>
                {
                    var currentTime = Element.Time;
                    var timeDialog = new TimePickerDialog(
                        Context,
                        (dialog, hour, minute) =>
                        {
                            Element.Time = new TimeSpan(hour, minute, 0);
                            // 关闭Dialog后手动清除焦点,触发Unfocus事件
                            Control.ClearFocus();
                        },
                        currentTime.Hours,
                        currentTime.Minutes,
                        true // 启用24小时模式
                    );
                    timeDialog.Show();
                };
            }

            // 订阅/取消订阅XF控件的焦点事件
            if (e.OldElement != null)
            {
                e.OldElement.Focused -= OnElementFocused;
                e.OldElement.Unfocused -= OnElementUnfocused;
            }

            if (e.NewElement != null)
            {
                e.NewElement.Focused += OnElementFocused;
                e.NewElement.Unfocused += OnElementUnfocused;
            }
        }

        private void OnControlFocusChanged(object sender, Android.Views.View.FocusChangeEventArgs e)
        {
            if (e.HasFocus)
            {
                Element?.Focus();
            }
            else
            {
                Element?.Unfocus();
            }
        }

        private void OnElementFocused(object sender, FocusEventArgs e)
        {
            if (Control != null && !Control.HasFocus)
            {
                Control.RequestFocus();
            }
        }

        private void OnElementUnfocused(object sender, FocusEventArgs e)
        {
            if (Control != null && Control.HasFocus)
            {
                Control.ClearFocus();
            }
        }

        protected override void Dispose(bool disposing)
        {
            if (disposing && Control != null)
            {
                Control.FocusChange -= OnControlFocusChanged;
            }
            base.Dispose(disposing);
        }
    }
}

2. 确保XF端正确订阅事件

在你的XAML或代码后台,确保TimePicker控件正确绑定了Focused和Unfocused事件:

XAML示例:

<TimePicker 
    x:Name="CustomTimePicker"
    Focused="CustomTimePicker_Focused"
    Unfocused="CustomTimePicker_Unfocused" />

代码后台示例:

CustomTimePicker.Focused += (sender, e) =>
{
    // 处理聚焦逻辑
    Console.WriteLine("TimePicker 已聚焦");
};

CustomTimePicker.Unfocused += (sender, e) =>
{
    // 处理失焦逻辑
    Console.WriteLine("TimePicker 已失焦");
};

3. 额外注意事项

  • 检查父布局的Focusable和FocusableInTouchMode属性,避免其他控件抢占焦点;
  • 测试时确保没有其他自定义渲染器或第三方库干扰TimePicker的焦点事件;
  • 如果使用了MVVM模式,可以通过行为(Behavior)来绑定焦点事件,效果是一样的。

我当时就是用这套方案解决的问题,Android端的Focused和Unfocused事件都能正常触发了,亲测有效!

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.20 07:57:19