Xamarin.Forms CollectionView在Android TV下Focus/Hover事件触发问题咨询
问题解答
实际获得焦点的元素
你在Xamarin.Forms/MAUI中看不到Focus事件触发,本质是因为CollectionView在Android平台的渲染逻辑是基于原生RecyclerView实现的,实际获得焦点的是原生RecyclerView中对应条目的ViewHolder根View,默认Xamarin.Forms/MAUI没有把原生层面的焦点变化事件向上传递到共享代码层的控件,所以你在共享代码里给StackLayout、Label加的Focus事件不会被触发。
实现焦点监听的方案
方案1:Xamarin.Forms 用自定义渲染器实现
第一步:共享代码层定义附加属性
用来接收焦点变化的回调,符合MVVM规范:
public static class FocusExtensions { public static readonly BindableProperty ItemFocusedCommandProperty = BindableProperty.CreateAttached("ItemFocusedCommand", typeof(ICommand), typeof(FocusExtensions), null); public static ICommand GetItemFocusedCommand(BindableObject view) { return (ICommand)view.GetValue(ItemFocusedCommandProperty); } public static void SetItemFocusedCommand(BindableObject view, ICommand value) { view.SetValue(ItemFocusedCommandProperty, value); } }
第二步:Android平台实现自定义CollectionView渲染器
[assembly: ExportRenderer(typeof(CollectionView), typeof(TvCollectionViewRenderer))] namespace YourAppNamespace.Droid.Renderers { public class TvCollectionViewRenderer : CollectionViewRenderer { public TvCollectionViewRenderer(Context context) : base(context) { } protected override void OnElementChanged(ElementChangedEventArgs<CollectionView> e) { base.OnElementChanged(e); if (e.NewElement != null && Control != null) { Control.ChildViewAdded += (s, a) => { // 给每个新增条目开启Android原生聚焦能力 a.Child.Focusable = true; a.Child.FocusableInTouchMode = true; // 绑定焦点变化监听 a.Child.FocusChange += (sender, focusArgs) => { if (focusArgs.HasFocus) { // 获取当前聚焦条目的位置和对应数据 var position = Control.GetChildAdapterPosition((Android.Views.View)sender); var focusItem = e.NewElement.ItemsSource.Cast<object>().ElementAt(position); // 触发绑定的命令 var command = FocusExtensions.GetItemFocusedCommand(e.NewElement); command?.Execute(focusItem); } }; }; } } } }
第三步:XAML中绑定使用
<CollectionView ItemsSource="{Binding Data}" local:FocusExtensions.ItemFocusedCommand="{Binding ItemFocusedCommand}"> <!-- 原有ItemsLayout、ItemTemplate等代码保持不变即可 --> </CollectionView>
之后在ViewModel中实现ItemFocusedCommand,就能实时拿到当前获得焦点的条目数据。
方案2:MAUI 适配方案
逻辑和Xamarin.Forms完全一致,只需要将自定义渲染器替换为MAUI的Handler实现,给RecyclerView的子条目添加同样的焦点监听逻辑即可。
额外适配注意点
Android TV平台所有可交互控件都需要显式设置focusable和focusableInTouchMode为true,才能正确响应D-Pad的焦点跳转,你也可以自定义焦点状态的背景drawable,优化交互体验。
内容的提问来源于stack exchange,提问作者Jono_2007
相关产品推荐
相关产品推荐

