.NET MAUI:滚动ListView时自动关闭SearchBar键盘的实现方案
解决ListView滚动时键盘不自动关闭的问题
方法一:通过状态标记区分手动滚动与列表更新触发的滚动
核心思路是区分用户手动滚动和列表数据更新触发的滚动,只在前者发生时关闭键盘:
定义两个变量用于状态管理:
private bool _isListUpdating; private CancellationTokenSource _cts;在SearchBar的
TextChanged事件中,标记列表更新状态并设置延迟:private void SearchBar_TextChanged(object sender, TextChangedEventArgs e) { // 取消之前的延迟任务 _cts?.Cancel(); _cts = new CancellationTokenSource(); // 标记列表正在更新 _isListUpdating = true; // 替换为你的实际列表数据过滤/更新逻辑 UpdateListViewData(e.NewTextValue); // 延迟500ms后标记更新完成,可根据实际更新速度调整时长 Task.Delay(500, _cts.Token).ContinueWith(t => { if (!t.IsCanceled) { _isListUpdating = false; } }, TaskScheduler.FromCurrentSynchronizationContext()); }在ListView的
Scrolled事件中,仅当列表不在更新状态时关闭键盘:private void ListView_Scrolled(object sender, ScrolledEventArgs e) { if (!_isListUpdating) { SearchBar.Unfocus(); } }
方法二:MAUI专属简化方案
如果使用MAUI,可直接利用PointerPressed事件监听用户触摸操作,触发时关闭键盘:
<ListView x:Name="ResultListView" ItemsSource="{Binding FilteredItems}" PointerPressed="ResultListView_PointerPressed"> <!-- 你的ItemTemplate定义 --> </ListView>
对应的后台代码:
private void ResultListView_PointerPressed(object sender, PointerEventArgs e) { SearchBar.Unfocus(); }
方法三:自定义触摸事件监听(跨平台兼容)
若上述方法仍存在误判,可通过自定义触摸效果监听ListView的触摸开始动作:
定义自定义路由效果:
public class ListViewTouchEffect : RoutingEffect { public event EventHandler TouchStarted; public ListViewTouchEffect() : base("YourAppNamespace.ListViewTouchEffect") { } public void OnTouchStarted() { TouchStarted?.Invoke(this, EventArgs.Empty); } }平台特定实现(以Android为例):
[assembly: ResolutionGroupName("YourAppNamespace")] [assembly: ExportEffect(typeof(AndroidListViewTouchEffect), "ListViewTouchEffect")] namespace YourApp.Droid.Effects { public class AndroidListViewTouchEffect : PlatformEffect { protected override void OnAttached() { if (Control is Android.Widget.ListView listView) { listView.Touch += ListView_Touch; } } private void ListView_Touch(object sender, Android.Views.View.TouchEventArgs e) { if (e.Event.Action == Android.Views.MotionEventActions.Down) { var effect = Element.Effects.FirstOrDefault(e => e is ListViewTouchEffect) as ListViewTouchEffect; effect?.OnTouchStarted(); } } protected override void OnDetached() { if (Control is Android.Widget.ListView listView) { listView.Touch -= ListView_Touch; } } } }在XAML中绑定事件:
<ListView x:Name="ResultListView" ItemsSource="{Binding FilteredItems}"> <ListView.Effects> <local:ListViewTouchEffect TouchStarted="ListViewTouchStarted"/> </ListView.Effects> <!-- 你的ItemTemplate定义 --> </ListView>触发键盘关闭:
private void ListViewTouchStarted(object sender, EventArgs e) { SearchBar.Unfocus(); }
内容的提问来源于stack exchange,提问作者Mickaël
相关产品推荐
相关产品推荐

