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

.NET MAUI:滚动ListView时自动关闭SearchBar键盘的实现方案

解决ListView滚动时键盘不自动关闭的问题

方法一:通过状态标记区分手动滚动与列表更新触发的滚动

核心思路是区分用户手动滚动和列表数据更新触发的滚动,只在前者发生时关闭键盘:

  1. 定义两个变量用于状态管理:

    private bool _isListUpdating;
    private CancellationTokenSource _cts;
    
  2. 在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());
    }
    
  3. 在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的触摸开始动作:

  1. 定义自定义路由效果:

    public class ListViewTouchEffect : RoutingEffect
    {
        public event EventHandler TouchStarted;
    
        public ListViewTouchEffect() : base("YourAppNamespace.ListViewTouchEffect")
        {
        }
    
        public void OnTouchStarted()
        {
            TouchStarted?.Invoke(this, EventArgs.Empty);
        }
    }
    
  2. 平台特定实现(以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;
                }
            }
        }
    }
    
  3. 在XAML中绑定事件:

    <ListView x:Name="ResultListView" ItemsSource="{Binding FilteredItems}">
        <ListView.Effects>
            <local:ListViewTouchEffect TouchStarted="ListViewTouchStarted"/>
        </ListView.Effects>
        <!-- 你的ItemTemplate定义 -->
    </ListView>
    
  4. 触发键盘关闭:

    private void ListViewTouchStarted(object sender, EventArgs e)
    {
        SearchBar.Unfocus();
    }
    

内容的提问来源于stack exchange,提问作者Mickaël

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.11 05:32:39