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

Flutter实现ListView选中项侧边切角布局的方法

实现ListView选中项右侧切角效果

要实现你想要的选中项右侧带切角的效果,可以通过**自定义裁剪器(CustomClipper)**结合选中状态管理来完成,具体步骤如下:

1. 维护选中状态

在你的State类中添加变量记录当前选中的列表项索引:

int? _selectedIndex;

2. 自定义切角裁剪器

创建一个裁剪器,给选中项右侧生成斜切角形状:

class RightCutClipper extends CustomClipper<Path> {
  @override
  Path getClip(Size size) {
    final path = Path();
    // 绘制路径:左上角 → 右上角左移20 → 右侧中点 → 右下角左移20 → 左下角 → 闭合
    path.moveTo(0, 0);
    path.lineTo(size.width - 20, 0);
    path.lineTo(size.width, size.height / 2);
    path.lineTo(size.width - 20, size.height);
    path.lineTo(0, size.height);
    path.close();
    return path;
  }

  @override
  bool shouldReclip(covariant CustomClipper<Path> oldClipper) => false;
}

你可以调整size.width - 20中的20来改变切角宽度,数值越大切角越宽。

3. 修改列表项构建逻辑

在itemBuilder中根据选中状态应用裁剪器和背景色,同时添加点击事件切换选中状态:

itemBuilder: (BuildContext context, int index) {
  final isSelected = _selectedIndex == index;
  return GestureDetector(
    onTap: () {
      setState(() {
        // 单选逻辑:点击已选中项取消选中,否则切换选中
        _selectedIndex = _selectedIndex == index ? null : index;
      });
    },
    child: ClipPath(
      clipper: isSelected ? RightCutClipper() : null,
      child: Container(
        width: double.infinity,
        padding: const EdgeInsets.symmetric(
          horizontal: PaddingSystem.padding24,
          vertical: SizeSystem.size16,
        ),
        color: isSelected ? ColorSystem.blue1 : Colors.transparent,
        child: // 替换成你的列表项内容,比如文本、图标组合
            Text(teamTaskList[index], style: TextStyle(color: isSelected ? Colors.white : Colors.black)),
      ),
    ),
  );
},

4. 调整分隔线(可选)

如果原有分隔线和选中背景不协调,可以把分隔线整合到列表项底部:

// 在列表项的Container中添加底部边框,替代原来的separatorBuilder
Container(
  width: double.infinity,
  padding: const EdgeInsets.symmetric(horizontal: PaddingSystem.padding24, vertical: SizeSystem.size16),
  decoration: BoxDecoration(
    border: index != teamTaskList.length - 1 
        ? Border(bottom: BorderSide(color: ColorSystem.black.withOpacity(0.1), width: SizeSystem.size1))
        : null,
  ),
  color: isSelected ? ColorSystem.blue1 : Colors.transparent,
  // ... 列表项内容
)

这样分隔线会和列表项背景自然融合,不会被选中的蓝色覆盖。

内容的提问来源于stack exchange,提问作者Ryan Mclaren

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.20 11:36:27