您好,GestureDetector、Pan 和 Scale 问题

Hello, issue with GestureDetector, Pan and Scale issue

我有一个代码可以让我用手指在图像上移动文本,还可以用双指在文本上缩放文本,但是有两个问题,在 google,希望有人能帮帮我,第一个问题是:

如果我取消对注释代码的注释,我会得到这个错误:

*构建主页时引发了以下断言(脏,状态:_HomePageState#8b5a9): GestureDetector 参数不正确。 同时拥有平移手势识别器和缩放手势识别器是多余的; scale 是 pan 的超集。 只需使用比例手势识别器。 *

如果我只使用scale,delta(details.delta.dx)在scale中不可用,所以我得到一个错误。

另一个问题是: 当我在我的文本小部件中设置 textScaleFactor: _scaleFactor 时,文本消失了,我该如何解决这个问题?非常感谢大家。

import 'package:flutter/material.dart';

void main() {
  runApp(const TextOverImage());
}

class TextOverImage extends StatelessWidget {
  const TextOverImage({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    // Size size = MediaQuery.of(context).size;
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          centerTitle: true,
          title: const Text('Text Over Image Image Example'),
        ),
        body: Center(
          child: Container(
            height: 300,
            width: 300,
            child: Stack(
              children: <Widget>[
                Container(
                  decoration: BoxDecoration(
                      borderRadius: BorderRadius.circular(5),
                      color: Colors.blue,
                      image: const DecorationImage(
                          image: NetworkImage(
                              "https://thumbs.dreamstime.com/b/funny-face-baby-27701492.jpg"),
                          fit: BoxFit.fill)),
                ),
                const HomePage()
              ],
            ),
          ),
        ),
      ),
    );
  }
}

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

  @override
  _HomePageState createState() => _HomePageState();
}

class _HomePageState extends State<HomePage> {
  Offset offset = Offset.zero;
  Offset offset2 = Offset.zero;

  double scale = 0.0;
  double _scaleFactor = 1.0;
  double _baseScaleFactor = 1.0;
  double _savedVal = 1.0;

  @override
  Widget build(BuildContext context) {
    return Stack(
      children: [
        Positioned(
          left: offset.dx,
          top: offset.dy,
          child: Row(
            children: [
              GestureDetector(
                onPanUpdate: (details) {
                  setState(() {
                    offset = Offset(offset.dx + details.delta.dx,
                        offset.dy + details.delta.dy);
                  });
                },

                // behavior: HitTestBehavior.translucent,
                //
                // onScaleStart: (details) {
                //   _baseScaleFactor = _scaleFactor;
                //
                // },
                //
                // onScaleUpdate: (details) {
                //   setState(() {
                //     _scaleFactor = _baseScaleFactor * details.scale;
                //   });
                // },

                child:  SizedBox(
                  width: 300,
                  height: 300,
                  child: Padding(
                    padding: const EdgeInsets.all(8.0),
                    child: Center(

                      child: Text("You Think You Are Funny But You Are Not",

                          // here if I remove _scaleFactor the text is GONE
                          textScaleFactor: _scaleFactor,
                          textAlign: TextAlign.center,
                          style: const TextStyle(
                              fontWeight: FontWeight.bold,
                              fontSize: 18.0,
                              color: Colors.red)),
                    ),
                  ),
                ),
              ),
            ],
          ),
        ),
        Positioned(
          left: offset2.dx,
          top: offset2.dy,
          child: Row(
            children: [
              GestureDetector(
                onPanUpdate: (details) {
                  setState(() {
                    offset2 = Offset(offset2.dx + details.delta.dx,
                        offset2.dy + details.delta.dy);
                  });
                },
                child: const SizedBox(
                  width: 300,
                  height: 300,
                  child: Padding(
                    padding: EdgeInsets.all(8.0),
                    child: Center(
                      child: Text("xx xxxx x xx   x x xxxxxx",
                          textAlign: TextAlign.center,
                          style: TextStyle(
                              fontWeight: FontWeight.bold,
                              fontSize: 18.0,
                              color: Colors.red)),
                    ),
                  ),
                ),
              ),
            ],
          ),
        ),
      ],
    );
  }
}

您可以使用 matrix_gesture_detector 包中的 MatrixGestureDetector 实现该功能。

直接实施如下:

class FloatingWidget extends StatefulWidget  {

  final Widget child;

  const FloatingWidget({Key? key, required this.child}) : super(key: key);

  @override
  State<FloatingWidget> createState() => _FloatingWidgetState();
}

class _FloatingWidgetState extends State<FloatingWidget> {

  Matrix4 _transform = Matrix4.identity();

  @override
  Widget build(BuildContext context) => Transform(
    transform: _transform,
    child: MatrixGestureDetector(
      onMatrixUpdate: (matrix, translationDeltaMatrix, scaleDeltaMatrix, rotationDeltaMatrix)  {
        setState(() {
          _transform = matrix;
        });
      },
      child: widget.child,
    ),
  );
}

在你的情况下,

import 'package:flutter/material.dart';
import 'package:matrix_gesture_detector/matrix_gesture_detector.dart';

void main() {
  runApp(const TextOverImage());
}

class TextOverImage extends StatelessWidget {
  const TextOverImage({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    // Size size = MediaQuery.of(context).size;
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          centerTitle: true,
          title: const Text('Text Over Image Image Example'),
        ),
        body: Center(
          child: SizedBox.fromSize(
            size: const Size(300, 300),
            child: Stack(
              children: <Widget>[
                Container(
                  decoration: BoxDecoration(
                      borderRadius: BorderRadius.circular(5),
                      color: Colors.blue,
                      image: const DecorationImage(
                          image: NetworkImage(
                              "https://thumbs.dreamstime.com/b/funny-face-baby-27701492.jpg"),
                          fit: BoxFit.fill)),
                ),
                const HomePage()
              ],
            ),
          ),
        ),
      ),
    );
  }
}

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

  @override
  _HomePageState createState() => _HomePageState();
}

class _HomePageState extends State<HomePage> {

  @override
  Widget build(BuildContext context) {
    return Stack(
      children: [
        FloatingWidget(
          child: Row(
            children: [
              SizedBox.fromSize(
                size: const Size(300, 300),
                child: const Padding(
                  padding: EdgeInsets.all(8.0),
                  child: Center(
                    child: Text("You Think You Are Funny But You Are Not",
                    textAlign: TextAlign.center,
                    style: TextStyle(
                        fontWeight: FontWeight.bold,
                        fontSize: 18.0,
                        color: Colors.red,
                      )
                    ),
                  ),
                ),
              ),
            ],
          ),
        ),
        FloatingWidget(
          child: Row(
            children: [
              SizedBox.fromSize(
                size: const Size(300, 300),
                child: const Padding(
                  padding: EdgeInsets.all(8.0),
                  child: Center(
                    child: Text("xx xxxx x xx   x x xxxxxx",
                      textAlign: TextAlign.center,
                      style: TextStyle(
                        fontWeight: FontWeight.bold,
                        fontSize: 18.0,
                        color: Colors.red,
                      ),
                    ),
                  ),
                ),
              ),
            ],
          ),
        ),
      ],
    );
  }
}

嗯,缩放手势是平移手势的超集,你可以得到它的 offset delta 作为

scaleUpdateDetails.focalPointDelta

目前我不知道文本比例因子问题,但如果您使用 Transform 小部件,它就无关紧要了。

要了解有关变换小部件的更多信息,我建议 this article 来自 Medium。