Android平板上Xamarin.Forms EntryCell输入字符后丢失焦点问题
Android平板TableView中EntryCell输入时失焦问题解决
问题现象
- 在Android平板设备上,
TableView下的EntryCell输入字符时会自动失去焦点,该问题仅出现在Android平板 - 重置
TableSection时,EntryCell同样会丢失焦点
复现代码
XAML代码
<?xml version="1.0" encoding="utf-8" ?> <ContentPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" x:Class="App1.MainPage"> <StackLayout> <TableView> <TableRoot> <TableSection x:Name="TS"> <EntryCell PropertyChanged="EntryCell_PropertyChanged" /> </TableSection> </TableRoot> </TableView> </StackLayout> </ContentPage>
C#代码
using Xamarin.Forms; namespace App1 { public partial class MainPage : ContentPage { public MainPage() { InitializeComponent(); } private void EntryCell_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e) { if (e.PropertyName == EntryCell.TextProperty.PropertyName) { Device.BeginInvokeOnMainThread(() => { TS.Add(new TextCell() { Text = "Test" }); }); } } } }
问题原因
每次输入字符触发EntryCell的PropertyChanged事件后,直接调用TableSection.Add()会触发TableView的布局重新计算。Android平板的焦点管理机制在布局刷新时,会默认清除当前输入控件的焦点;重置TableSection时会重建整个列表的子元素,同样会导致焦点丢失。
解决方案
1. 添加输入防抖延迟更新
通过防抖机制,等待用户停止输入一段时间后再更新TableSection,减少布局刷新的频率,避免频繁触发焦点丢失。
修改后的C#代码:
using Xamarin.Forms; using System.Timers; namespace App1 { public partial class MainPage : ContentPage { private Timer _debounceTimer; public MainPage() { InitializeComponent(); // 设置500ms防抖延迟,可根据需求调整 _debounceTimer = new Timer(500); _debounceTimer.Elapsed += OnDebounceTimerElapsed; _debounceTimer.AutoReset = false; } private void EntryCell_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e) { if (e.PropertyName == EntryCell.TextProperty.PropertyName) { // 每次输入重置计时器 _debounceTimer.Stop(); _debounceTimer.Start(); } } private void OnDebounceTimerElapsed(object sender, ElapsedEventArgs e) { Device.BeginInvokeOnMainThread(() => { TS.Add(new TextCell() { Text = "Test" }); }); } protected override void OnDisappearing() { _debounceTimer?.Dispose(); base.OnDisappearing(); } } }
2. 改用ViewCell包裹Entry手动控制焦点
放弃EntryCell,使用ViewCell嵌套原生Entry控件,在更新列表后手动恢复焦点,彻底解决焦点丢失问题。
修改后的XAML代码:
<?xml version="1.0" encoding="utf-8" ?> <ContentPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" x:Class="App1.MainPage"> <StackLayout> <TableView> <TableRoot> <TableSection x:Name="TS"> <ViewCell> <Entry x:Name="InputEntry" TextChanged="InputEntry_TextChanged" /> </ViewCell> </TableSection> </TableRoot> </TableView> </StackLayout> </ContentPage>
对应的C#代码:
using Xamarin.Forms; namespace App1 { public partial class MainPage : ContentPage { public MainPage() { InitializeComponent(); } private void InputEntry_TextChanged(object sender, TextChangedEventArgs e) { Device.BeginInvokeOnMainThread(() => { TS.Add(new TextCell() { Text = "Test" }); // 更新后手动重新获取焦点 InputEntry.Focus(); }); } } }
3. 使用绑定数据源刷新列表
通过ItemsSource绑定数据源的方式更新列表,替代直接修改TableSection的子元素集合,让TableView更高效地刷新,降低焦点丢失的概率。
实现代码:
using Xamarin.Forms; using System.Collections.ObjectModel; namespace App1 { public partial class MainPage : ContentPage { public ObservableCollection<Cell> SectionCells { get; set; } public MainPage() { InitializeComponent(); SectionCells = new ObservableCollection<Cell>(); // 添加自定义Entry控件 SectionCells.Add(new ViewCell { View = new Entry { TextChanged = InputEntry_TextChanged } }); TS.ItemsSource = SectionCells; BindingContext = this; } private void InputEntry_TextChanged(object sender, TextChangedEventArgs e) { SectionCells.Add(new TextCell { Text = "Test" }); } } }
方案选择
- 若需保留
EntryCell原生样式,优先选择防抖延迟更新方案 - 若需要精准控制焦点行为,优先选择ViewCell包裹Entry方案
- 若项目采用MVVM模式,优先选择绑定数据源方案
内容的提问来源于stack exchange,提问作者Charan Darbasthu
相关产品推荐
相关产品推荐

