通过滑动(运动事件)颤动多个字母选择

flutter multiple letter selection by sliding ( motion event )

我需要通过拖动字母来创建单词。 我搜索但找不到足够的代码来检测运动事件。 我想用手指轻扫 select 多个字母,并从 select 编辑的字母创建单词。 我需要制作一个如下所示的文字益智游戏。 我怎样才能制作这样的游戏?

您应该试用 GestureDetector 并使用其平移 drags gesture in Flutter

为此,您只需将 GestureDetector 作为持有字母的圆形 Widget 的父级并检测被拖动的内容。

我想这正是您想要的。

import 'package:flutter/material.dart';
import 'dart:math' as math;

import 'package:flutter/services.dart';

class DrawPatternGame extends StatefulWidget {
  const DrawPatternGame({Key? key}) : super(key: key);

  @override
  State<DrawPatternGame> createState() => _DrawPatternGameState();
}

class _DrawPatternGameState extends State<DrawPatternGame> {
  List<String> stringList = ["E", "L", "A", "K", "İ", "N", "U", "G"];
  List<String> selectedLetter = [];

  double radius = 80;
  List<Offset> endLineOffsetList = [];
  List<Offset> letterOffsetList = [];

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("Draw Game"),
      ),
      body: Column(
        mainAxisAlignment: MainAxisAlignment.spaceAround,
        children: [
          Container(
            height: 300,
            color: Colors.green,
            child: Center(
                child: Container(
              padding: selectedLetter.isNotEmpty
                  ? EdgeInsets.fromLTRB(8, 8, 8, 0)
                  : EdgeInsets.zero,
              decoration: BoxDecoration(
                  color: Colors.pink, borderRadius: BorderRadius.circular(32)),
              child: Text(
                selectedLetter.toSet().join(),
                textAlign: TextAlign.center,
                style: TextStyle(
                  color: Colors.white,
                  letterSpacing: 8,
                  fontSize: 32,
                  fontWeight: FontWeight.bold,
                ),
              ),
            )),
          ),
          Center(
            child: GestureDetector(
              onPanStart: (details) {
                Offset correctedOffset = Offset(details.localPosition.dx - 104,
                    details.localPosition.dy - 104);
                for (var i = 0; i < letterOffsetList.length; i++) {
                  if ((correctedOffset - (letterOffsetList[i])).distance < 24 &&
                      !selectedLetter.contains(stringList[i])) {
                    selectedLetter.add(stringList[i]);
                    print(stringList[i]);

                    endLineOffsetList
                      ..add(letterOffsetList[i])
                      ..add(letterOffsetList[i]);
                    setState(() {});
                    letterOffsetList = [];
                    break;
                  }
                }
              },
              onPanUpdate: (details) {
                if (endLineOffsetList.isNotEmpty &&
                    selectedLetter.length < stringList.length) {
                  Offset correctedOffset = Offset(
                      details.localPosition.dx - 104,
                      details.localPosition.dy - 104);
                  endLineOffsetList[endLineOffsetList.length - 1] =
                      correctedOffset;
                  for (var i = 0; i < letterOffsetList.length; i++) {
                    if ((correctedOffset - (letterOffsetList[i])).distance <
                            24 &&
                        !selectedLetter.contains(stringList[i])) {
                      endLineOffsetList[endLineOffsetList.length - 1] =
                          letterOffsetList[i];
                      selectedLetter.add(stringList[i]);
                      endLineOffsetList.add(letterOffsetList[i]);
                      print(stringList[i]);
                      Feedback.forTap(context);

                      break;
                    }
                  }
                  setState(() {});
                  letterOffsetList = [];
                }
              },
              onPanEnd: (details) {
                selectedLetter = [];

                endLineOffsetList = [];

                setState(() {});
              },
              child: Stack(
                alignment: Alignment.center,
                children: [
                  CircleAvatar(
                    radius: radius + 32,
                  ),
                  CustomPaint(
                    painter: LinePainter(endLineOffsetList: endLineOffsetList),
                  ),
                  ...List.generate(
                    stringList.length,
                    (i) {
                      letterOffsetList.add(Offset(
                          radius *
                              math.cos(2 * i * math.pi / stringList.length),
                          radius *
                              math.sin(2 * i * math.pi / stringList.length)));
                      return Transform.translate(
                        offset: letterOffsetList[i],
                        child: CircleAvatar(
                          backgroundColor:
                              selectedLetter.contains(stringList[i])
                                  ? Colors.pink
                                  : null,
                          child: SizedBox(
                            width: 32,
                            height: 32,
                            child: Text(
                              stringList[i],
                              textAlign: TextAlign.center,
                              style: TextStyle(
                                color: Colors.white,
                                fontSize: 32,
                                fontWeight: FontWeight.bold,
                              ),
                            ),
                          ),
                        ),
                      );
                    },
                  )
                ],
              ),
            ),
          )
        ],
      ),
    );
  }
}

class LinePainter extends CustomPainter {
  final List<Offset>? endLineOffsetList;
  LinePainter({this.endLineOffsetList});
  @override
  void paint(Canvas canvas, Size size) {
    var paint = Paint()
      ..color = Colors.pink
      ..strokeWidth = 5
      ..strokeCap = StrokeCap.round;
    if (endLineOffsetList != null && endLineOffsetList!.length >= 2) {
      for (var i = 0; i < endLineOffsetList!.length - 1; ++i) {
        canvas.drawLine(
            endLineOffsetList![i], endLineOffsetList![i + 1], paint);
      }
    }
  }

  @override
  bool shouldRepaint(LinePainter oldDelegate) => true;

  @override
  bool shouldRebuildSemantics(LinePainter oldDelegate) => true;
}