如何用Flutter Custom Painter实现单词搜索游戏的可选划线功能
Flutter单词搜索游戏划线选择效果实现方案
你当前用ListView.Builder拆分渲染每个字母块的方案,天然不支持跨item的连续滑动手势捕获,很难实现连贯的划线选择效果,推荐改用自定义绘制+全局手势监听的方案实现,具体步骤如下:
- 第一步:重构网格数据结构,放弃用
ListView.Builder拼接独立字母item,改用统一容器渲染所有字母,提前把每个字母的坐标、尺寸、字符存入二维数组,示例结构:
class LetterCell { final String char; final Offset center; final Size cellSize; bool isSelected = false; LetterCell(this.char, this.center, this.cellSize); } // 初始化网格数据时遍历计算每个cell的位置 List<List<LetterCell>> letterGrid = [];
- 第二步:给整个网格区域加
GestureDetector,监听滑动全周期事件,实时计算触摸点命中的字母块:- 按下时清空上一次的选中列表,检测首次命中的cell加入选中列表,记录初始选择方向
- 滑动过程中实时检测当前触摸点命中的cell,仅当cell和上一个选中cell为相邻(支持上下左右/斜向)、且和初始选择方向一致时,才加入选中列表
- 滑动结束后校验选中的字符拼接后是否匹配题库中的有效单词
- 第三步:用
CustomPaint绘制选中高亮效果:- 遍历选中cell列表,连接所有cell的中心点绘制半透明高亮描边,也可以直接给选中cell绘制填充背景
- 如果需要实现跟随手指的实时预览效果,可以额外绘制从最后一个选中cell中心到当前触摸点的虚线提示
- 第四步:单词校验通过后,将对应cell的选中状态永久标记,下次绘制时直接渲染固定高亮效果,无需再跟随手势变化
如果一定要保留ListView.Builder的实现结构,可以给每个字母item加Listener监听指针事件,同时用全局GestureArenaManager接管跨item的手势分发,但该方案实现复杂度高、手势冲突概率大,更推荐用上述自定义绘制方案。
核心实现参考代码:
GestureDetector( onPanStart: (details) { _clearCurrentSelection(); _checkTouchHitCell(details.localPosition); }, onPanUpdate: (details) { _checkTouchHitCell(details.localPosition); _currentTouchPosition = details.localPosition; setState(() {}); }, onPanEnd: (details) { _validateSelectedWord(); _currentTouchPosition = null; setState(() {}); }, child: CustomPaint( painter: WordSearchPainter( letterGrid: letterGrid, selectedCells: _selectedCells, currentTouchPos: _currentTouchPosition, ), size: Size(gridTotalWidth, gridTotalHeight), ), )
内容的提问来源于stack exchange,提问作者HasanToufiqAhamed
相关产品推荐
相关产品推荐

