如何用两根手指放大/缩小文本?

时间:2019-03-31 10:54:50

标签: dart flutter gesture pinchzoom

我正在创建一个文本字段,例如Text或RichText。然后,我想使用捏放大/缩小文本的大小。现在,我尝试实现GestureDetector,但它也可以用一根手指放大/缩小。而且,目标锁定检测确实很困难。有时会冻结。捏定冻结后,我会添加视频,然后突然变大。第二个视频是这样的情况:仅当我用一根手指点击文本并移至左上角时,图像才会放大。理想的实现是检测捏和放大/缩小所有文本区域。当我只用一根手指时,请禁用缩放。您能给我一些提示,链接或代码如何解决或在哪里找到解决方案? enter image description here enter image description here

      body: GestureDetector(
          onScaleUpdate: (details) {
            setState(() {
              _textSize =
                  _initTextSize + (_initTextSize * (details.scale * .35));
            });
          },
          onScaleEnd: (ScaleEndDetails details) {
            setState(() {
              _initTextSize = _textSize;
            });
          },
          child: Center(
              child: SizedBox(
            height: _textSize,
            child: FittedBox(
              child: Text("Test"),
            ),
          ))),

4 个答案:

答案 0 :(得分:6)

在具有这些配置的有状态小组件中

double _scaleFactor = 1.0;
double _baseScaleFactor = 1.0;

并仅在更新时使用setState,并使用scaleFactor的{​​{1}}属性上的textScaleFactor

只有一个setState可以在开始缩放时重建小部件并存储初始因子

RichText

我输入的高度和宽度只是为了扩展并模拟手势检测器的区域。

答案 1 :(得分:3)

Google软件工程师Gary Qian和Chris Yang在他们的Google Developer Days演讲中证明了这一点。该视频可在此处查看:

这里的代码与其他一些答案类似,但是它们特别添加了一个钳位,以使其不会太大或太小。

以下是其可扩展文本气泡的摘要:

enter image description here

因为即使单指触摸仍会调用缩放,所以我添加了对scaleUpdateDetails.scale == 1.0的检查。这意味着如果比例不变,则不会更新用户界面。

class Bubble extends StatelessWidget {
  @override
  _BubbleState createState() => _BubbleState();
}

class _BubbleState extends State<Bubble> {
  double _fontSize = 20;
  final double _baseFontSize = 20;
  double _fontScale = 1;
  double _baseFontScale = 1;

  @override
  Widget build(BuildContext context) {
    return GestureDetector(
      onScaleStart: (ScaleStartDetails scaleStartDetails) {
        _baseFontScale = _fontScale;
      },
      onScaleUpdate: (ScaleUpdateDetails scaleUpdateDetails) {
        // don't update the UI if the scale didn't change
        if (scaleUpdateDetails.scale == 1.0) {
          return;
        }
        setState(() {
          _fontScale = (_baseFontScale * scaleUpdateDetails.scale).clamp(0.5, 5.0);
          _fontSize = _fontScale * _baseFontSize;
        });
      },
      child: ...
        // descendant with a Text widget that uses the _fontSize
    );
  }
}

注意:

  • 使用StatelessWidget,以便您可以随时存储当前字体大小和缩放比例。
  • 使用另外两个变量来记住原始字体大小以及捏紧开始时的缩放比例
  • 将“文本”小部件包装在GestureDetector
  • 将原始比例保存到onScaleStart
  • 计算新字体大小onScaleUpdate
  • 使用setState来以新的大小重建小部件

答案 2 :(得分:0)

解决方案:两指放大和缩小。

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

  class TransformText extends StatefulWidget {
    TransformText({Key key}) : super(key: key); // changed

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

  class _TransformTextState extends State<TransformText> {
    double scale = 0.0;

    @override
    Widget build(BuildContext context) {
      final ValueNotifier<Matrix4> notifier = ValueNotifier(Matrix4.identity());

      return Scaffold(
        appBar: AppBar(
          title: Text('Single finger Rotate text'), // changed
        ),
        body: Center(
          child: MatrixGestureDetector(
            onMatrixUpdate: (m, tm, sm, rm) {
              notifier.value = m;
            },
            child: AnimatedBuilder(
              animation: notifier,
              builder: (ctx, child) {
                return Transform(
                  transform: notifier.value,
                  child: Center(
                    child: Stack(
                      children: <Widget>[
                        Container(
                          color: Colors.red,
                          padding: EdgeInsets.all(10),
                          margin: EdgeInsets.only(top: 50),
                          child: Transform.scale(
                            scale:
                                1, // make this dynamic to change the scaling as in the basic demo
                            origin: Offset(0.0, 0.0),
                            child: Container(
                              height: 100,
                              child: Text(
                                "Two finger to zoom!!",
                                style:
                                    TextStyle(fontSize: 26, color: Colors.white),
                              ),
                            ),
                          ),
                        ),
                      ],
                    ),
                  ),
                );
              },
            ),
          ),
        ),
      );
    }
  }

答案 3 :(得分:0)

完整代码。希望对您有所帮助。

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

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    final appTitle = 'Demo';

    return MaterialApp(
      title: appTitle,
      home: MyHomePage(title: appTitle),
    );
  }
}

class MyHomePage extends StatelessWidget {
  final String title;

  MyHomePage({Key key, this.title}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
          title: Text(title),
        ),
        body: TransformText());
  }
}

class TransformText extends StatefulWidget {
  TransformText({Key key}) : super(key: key); // changed

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

class _TransformTextState extends State<TransformText> {
  double scale = 0.0;
  double _scaleFactor = 1.0;
  double _baseScaleFactor = 1.0;
  double _savedVal = 1.0;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('GestureDetector Test'), // changed
      ),
      body: Column(
        children: <Widget>[
          RaisedButton(
              child: Text('get'),
              onPressed: () {
                _savedVal = _scaleFactor;
              }),
          RaisedButton(
              child: Text('set'),
              onPressed: () {
                setState(() {
                  _scaleFactor = _savedVal;
                });
              }),
          Expanded(
            child: Center(
                child: GestureDetector(
              behavior: HitTestBehavior.translucent,
              onScaleStart: (details) {
                _baseScaleFactor = _scaleFactor;
              },
              onScaleUpdate: (details) {
                setState(() {
                  _scaleFactor = _baseScaleFactor * details.scale;
                });
              },
              child: Container(
                height: MediaQuery.of(context).size.height,
                width: MediaQuery.of(context).size.width,
                child: Center(
                  child: Text(
                    'Test',
                    textScaleFactor: _scaleFactor,
                  ),
                ),
              ),
            )),
          ),
        ],
      ),
    );
  }
}