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

Flutter实现选中ListView/GridView组件时背景变暗并高亮组件的方案

Flutter列表项点击/长按高亮+背景变暗实现方案

自定义实现方法

你之前的问题出在把背景模糊/变暗的逻辑放在了列表项内部,导致列表复用和触摸拦截异常。正确思路是用Stack将列表和全局遮罩层分离,单独控制选中项的高亮样式:

核心逻辑

  • 用Stack包裹列表和半透明遮罩层,遮罩默认隐藏,有选中项时显示
  • 用Set<int>维护选中项索引集合,支持多选
  • 给列表项绑定点击/长按事件,更新选中状态并控制遮罩显示
  • 为选中项添加高亮样式(边框、背景色叠加等)

完整代码示例

import 'package:flutter/material.dart';

class SelectableListDemo extends StatefulWidget {
  const SelectableListDemo({super.key});

  @override
  State<SelectableListDemo> createState() => _SelectableListDemoState();
}

class _SelectableListDemoState extends State<SelectableListDemo> {
  // 存储选中的项索引
  final Set<int> _selectedIndexes = {};

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text("可选中列表")),
      body: Stack(
        children: [
          // 列表主体
          ListView.builder(
            itemCount: 15,
            itemBuilder: (ctx, index) {
              final isSelected = _selectedIndexes.contains(index);
              return GestureDetector(
                // 点击切换选中状态
                onTap: () {
                  setState(() {
                    isSelected 
                        ? _selectedIndexes.remove(index) 
                        : _selectedIndexes.add(index);
                  });
                },
                // 长按直接选中
                onLongPress: () {
                  setState(() => _selectedIndexes.add(index));
                },
                child: Container(
                  margin: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
                  padding: const EdgeInsets.all(16),
                  // 选中时的高亮样式
                  decoration: BoxDecoration(
                    color: isSelected ? Colors.blue.withOpacity(0.1) : Colors.white,
                    border: isSelected ? Border.all(color: Colors.blue, width: 2) : null,
                    borderRadius: BorderRadius.circular(8),
                  ),
                  child: Text("列表项 $index", style: const TextStyle(fontSize: 16)),
                ),
              );
            },
          ),
          // 背景变暗遮罩层(点击可清空选中)
          if (_selectedIndexes.isNotEmpty)
            GestureDetector(
              onTap: () => setState(() => _selectedIndexes.clear()),
              child: Container(color: Colors.black.withOpacity(0.4)),
            ),
        ],
      ),
    );
  }
}

细节调整

如果需要背景模糊效果,把遮罩层的Container替换为:

BackdropFilter(
  filter: ImageFilter.blur(sigmaX: 3, sigmaY: 3),
  child: Container(color: Colors.black.withOpacity(0.2)),
)

推荐第三方包

不想自定义的话,可用现成包快速实现:

  • flutter_multi_select_items:支持多选、高亮、自定义样式,适配ListView/GridView
  • selectable_container:轻量可选中容器组件,直接嵌套列表项即可

内容的提问来源于stack exchange,提问作者Cavin Macwan

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.03 11:15:29