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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.28 00:02:53