颤振 MatrixGestureDetector 规模所有表情符号变大并在屏幕中跳跃

2024-01-12

这段代码有什么问题?

我希望表情符号也像文本一样与文本一起正确缩放,但表情符号会跳跃并变大

如果我只放表情符号也会发生同样的问题

主程序.dart

Scaffold(
    appBar: AppBar(),  
    body: SizedBox(
      height: Get.height,
      width: Get.width,
      child: Stack(
        children: [
          TransformDemo(),
        ],
      ),
    ),
  );
}

变换演示.dart

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

class TransformDemo extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    final ValueNotifier<Matrix4> notifier = ValueNotifier(Matrix4.identity());
    return MatrixGestureDetector(
      onMatrixUpdate: (m, tm, sm, rm) {
        notifier.value = m;
      },
      child: AnimatedBuilder(
        animation: notifier,
        builder: (ctx, child) {
          return Transform(
            transform: notifier.value,
            child: Align(
              alignment: Alignment.center,
              child: FittedBox(
                // fit: BoxFit.contain,
                child: Text('Hello world ???? ', style: TextStyle(fontSize: 60),)
                // child: Icon(Icons.favorite, color: Colors.deepPurple.withOpacity(0.5), size: 200),
              ),
            ),
          );
        },
      ),
    );
  }
}

矩阵手势检测器.dart

import 'dart:math';
import 'package:flutter/widgets.dart';

typedef MatrixGestureDetectorCallback = void Function(
    Matrix4 matrix,
    Matrix4 translationDeltaMatrix,
    Matrix4 scaleDeltaMatrix,
    Matrix4 rotationDeltaMatrix);

/// [MatrixGestureDetector] detects translation, scale and rotation gestures
/// and combines them into [Matrix4] object that can be used by [Transform] widget
/// or by low level [CustomPainter] code. You can customize types of reported
/// gestures by passing [shouldTranslate], [shouldScale] and [shouldRotate]
/// parameters.
///
class MatrixGestureDetector extends StatefulWidget {
  /// [Matrix4] change notification callback
  ///
  final MatrixGestureDetectorCallback onMatrixUpdate;

  /// The [child] contained by this detector.
  ///
  /// {@macro flutter.widgets.child}
  ///
  final Widget child;

  /// Whether to detect translation gestures during the event processing.
  ///
  /// Defaults to true.
  ///
  final bool shouldTranslate;

  /// Whether to detect scale gestures during the event processing.
  ///
  /// Defaults to true.
  ///
  final bool shouldScale;

  /// Whether to detect rotation gestures during the event processing.
  ///
  /// Defaults to true.
  ///
  final bool shouldRotate;

  /// Whether [ClipRect] widget should clip [child] widget.
  ///
  /// Defaults to true.
  ///
  final bool clipChild;

  /// The hit test behavior, passed to the underlying GestureDetector.
  ///
  /// Defaults to HitTestBehavior.deferToChild
  ///
  final HitTestBehavior behavior;

  /// When set, it will be used for computing a "fixed" focal point
  /// aligned relative to the size of this widget.
  final Alignment? focalPointAlignment;

  const MatrixGestureDetector({
    Key? key,
    required this.onMatrixUpdate,
    required this.child,
    this.shouldTranslate = true,
    this.shouldScale = true,
    this.shouldRotate = true,
    this.clipChild = true,
    this.focalPointAlignment,
    this.behavior = HitTestBehavior.deferToChild,
  })  : super(key: key);

  @override
  _MatrixGestureDetectorState createState() => _MatrixGestureDetectorState();

  ///
  /// Compose the matrix from translation, scale and rotation matrices - you can
  /// pass a null to skip any matrix from composition.
  ///
  /// If [matrix] is not null the result of the composing will be concatenated
  /// to that [matrix], otherwise the identity matrix will be used.
  ///
  static Matrix4 compose(Matrix4? matrix, Matrix4? translationMatrix,
      Matrix4? scaleMatrix, Matrix4? rotationMatrix) {
    if (matrix == null) matrix = Matrix4.identity();
    if (translationMatrix != null) matrix = translationMatrix * matrix;
    if (scaleMatrix != null) matrix = scaleMatrix * matrix;
    if (rotationMatrix != null) matrix = rotationMatrix * matrix;
    return matrix!;
  }

  ///
  /// Decomposes [matrix] into [MatrixDecomposedValues.translation],
  /// [MatrixDecomposedValues.scale] and [MatrixDecomposedValues.rotation] components.
  ///
  static MatrixDecomposedValues decomposeToValues(Matrix4 matrix) {
    var array = matrix.applyToVector3Array([0, 0, 0, 1, 0, 0]);
    Offset translation = Offset(array[0], array[1]);
    Offset delta = Offset(array[3] - array[0], array[4] - array[1]);
    double scale = delta.distance;
    double rotation = delta.direction;
    return MatrixDecomposedValues(translation, scale, rotation);
  }
}

class _MatrixGestureDetectorState extends State<MatrixGestureDetector> {
  Matrix4 translationDeltaMatrix = Matrix4.identity();
  Matrix4 scaleDeltaMatrix = Matrix4.identity();
  Matrix4 rotationDeltaMatrix = Matrix4.identity();
  Matrix4 matrix = Matrix4.identity();

  @override
  Widget build(BuildContext context) {
    Widget child =
    widget.clipChild ? ClipRect(child: widget.child) : widget.child;
    return GestureDetector(
      behavior: widget.behavior,
      onScaleStart: onScaleStart,
      onScaleUpdate: onScaleUpdate,
      child: child,
    );
  }

  _ValueUpdater<Offset> translationUpdater = _ValueUpdater(
    value: Offset.zero,
    onUpdate: (oldVal, newVal) => newVal - oldVal,
  );
  _ValueUpdater<double> scaleUpdater = _ValueUpdater(
    value: 1.0,
    onUpdate: (oldVal, newVal) => newVal / oldVal,
  );
  _ValueUpdater<double> rotationUpdater = _ValueUpdater(
    value: 0.0,
    onUpdate: (oldVal, newVal) => newVal - oldVal,
  );

  void onScaleStart(ScaleStartDetails details) {
    translationUpdater.value = details.focalPoint;
    scaleUpdater.value = 1.0;
    rotationUpdater.value = 0.0;
  }

  void onScaleUpdate(ScaleUpdateDetails details) {
    translationDeltaMatrix = Matrix4.identity();
    scaleDeltaMatrix = Matrix4.identity();
    rotationDeltaMatrix = Matrix4.identity();

    // handle matrix translating
    if (widget.shouldTranslate) {
      Offset translationDelta = translationUpdater.update(details.focalPoint);
      translationDeltaMatrix = _translate(translationDelta);
      matrix = translationDeltaMatrix * matrix;
    }

    final focalPointAlignment = widget.focalPointAlignment;
    final focalPoint = focalPointAlignment == null ?
    details.localFocalPoint :
    focalPointAlignment.alongSize(context.size!);

    // handle matrix scaling
    if (widget.shouldScale && details.scale != 1.0) {
      double scaleDelta = scaleUpdater.update(details.scale);
      scaleDeltaMatrix = _scale(scaleDelta, focalPoint);
      matrix = scaleDeltaMatrix * matrix;
    }

    // handle matrix rotating
    if (widget.shouldRotate && details.rotation != 0.0) {
      double rotationDelta = rotationUpdater.update(details.rotation);
      rotationDeltaMatrix = _rotate(rotationDelta, focalPoint);
      matrix = rotationDeltaMatrix * matrix;
    }

    widget.onMatrixUpdate(
        matrix, translationDeltaMatrix, scaleDeltaMatrix, rotationDeltaMatrix);
  }

  Matrix4 _translate(Offset translation) {
    var dx = translation.dx;
    var dy = translation.dy;

    //  ..[0]  = 1       # x scale
    //  ..[5]  = 1       # y scale
    //  ..[10] = 1       # diagonal "one"
    //  ..[12] = dx      # x translation
    //  ..[13] = dy      # y translation
    //  ..[15] = 1       # diagonal "one"
    return Matrix4(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, dx, dy, 0, 1);
  }

  Matrix4 _scale(double scale, Offset focalPoint) {
    var dx = (1 - scale) * focalPoint.dx;
    var dy = (1 - scale) * focalPoint.dy;

    //  ..[0]  = scale   # x scale
    //  ..[5]  = scale   # y scale
    //  ..[10] = 1       # diagonal "one"
    //  ..[12] = dx      # x translation
    //  ..[13] = dy      # y translation
    //  ..[15] = 1       # diagonal "one"
    return Matrix4(scale, 0, 0, 0, 0, scale, 0, 0, 0, 0, 1, 0, dx, dy, 0, 1);
  }

  Matrix4 _rotate(double angle, Offset focalPoint) {
    var c = cos(angle);
    var s = sin(angle);
    var dx = (1 - c) * focalPoint.dx + s * focalPoint.dy;
    var dy = (1 - c) * focalPoint.dy - s * focalPoint.dx;

    //  ..[0]  = c       # x scale
    //  ..[1]  = s       # y skew
    //  ..[4]  = -s      # x skew
    //  ..[5]  = c       # y scale
    //  ..[10] = 1       # diagonal "one"
    //  ..[12] = dx      # x translation
    //  ..[13] = dy      # y translation
    //  ..[15] = 1       # diagonal "one"
    return Matrix4(c, s, 0, 0, -s, c, 0, 0, 0, 0, 1, 0, dx, dy, 0, 1);
  }
}

typedef _OnUpdate<T> = T Function(T oldValue, T newValue);

class _ValueUpdater<T> {
  final _OnUpdate<T> onUpdate;
  T value;

  _ValueUpdater({
    required this.value,
    required this.onUpdate,
  });

  T update(T newValue) {
    T updated = onUpdate(value, newValue);
    value = newValue;
    return updated;
  }
}

class MatrixDecomposedValues {
  /// Translation, in most cases useful only for matrices that are nothing but
  /// a translation (no scale and no rotation).
  final Offset translation;

  /// Scaling factor.
  final double scale;

  /// Rotation in radians, (-pi..pi) range.
  final double rotation;

  MatrixDecomposedValues(this.translation, this.scale, this.rotation);

  @override
  String toString() {
    return 'MatrixDecomposedValues(translation: $translation, scale: ${scale.toStringAsFixed(3)}, rotation: ${rotation.toStringAsFixed(3)})';
  }
}

您所看到的情况是由当前版本的 Flutter 中的一个已知问题引起的。当文字太大时,表情符号就会变得很大。

要重现它,您只需将文本放大即可:

Text(
  'Hi ???? ',
  style: TextStyle(fontSize: 100),
),

示例输出:

请参阅问题:https://github.com/flutter/flutter/issues/110726 https://github.com/flutter/flutter/issues/110726。目前,我想说的是,请继续关注 flutter 团队的补丁。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

颤振 MatrixGestureDetector 规模所有表情符号变大并在屏幕中跳跃 的相关文章

  • 如何获取每个StorageVolume的可用大小和总大小?

    背景 谷歌 悲伤 计划破坏存储权限 https www xda developers com android q storage access framework scoped storage 这样应用程序将无法使用标准文件 API 和文件
  • 我在布局上看不到任何 FirebaseRecyclerAdapter 项目

    我试图将数据从 Firebase 数据库检索到我的布局 但我看不到任何项目FirebaseRecyclerAdapter在布局中 请帮忙 我按照一个教程展示了如何做到这一点 当我运行应用程序时 我没有看到任何项目 但我可以滚动 public
  • 如何在android中显示保存在sdcard文件夹中的图像[关闭]

    这个问题不太可能对任何未来的访客有帮助 它只与一个较小的地理区域 一个特定的时间点或一个非常狭窄的情况相关 通常不适用于全世界的互联网受众 为了帮助使这个问题更广泛地适用 访问帮助中心 help reopen questions 当我正在显
  • AdapterContextMenuInfo 始终为 null

    我尝试通过 android 开发文档中的书来做到这一点 this didn t create a menu i don t know why registerForContextMenu getListView setListAdapter
  • 如何正确释放Android MediaPlayer

    我正在尝试向我的 Android 应用程序添加一个按钮 当点击该按钮时它会播放 MP3 我已经让它工作了 但没有办法释放 mediaPlayer 对象 因此即使在我离开活动后它仍然会继续播放 如果我在react 方法之外初始化MediaPl
  • Gradle 构建错误:无法从 https://repo1.maven.org/maven2/io/fabric/tools/gradle/maven-metadata.xml 加载 Maven 元数据

    我在 Android studio 中遇到 gradle 构建错误 如下所示 Error A problem occurred configuring project MyApp Could not resolve all dependen
  • Bitmap.getPixels() 中的 IllegalArgumentException

    我想将数据从位图复制到int using getPixels 这是我当前的代码 int pixels new int myBitmap getHeight myBitmap getWidth myBitmap getPixels pixel
  • ExoPlayer2 - 如何使 HTTP 301 重定向工作?

    我开始使用 ExoPlayer 来传输一些音频 一切都很顺利 直到我遇到一个带有 301 永久移动 重定向的 URL ExoPlayer2 默认情况下不处理该问题 我已经看过这个线程 https github com google ExoP
  • 在 android 中建立与 MySQL 的池连接

    我需要从我的 Android 应用程序访问 MySQL 数据库 现在所有的工作都通过 DriverManager getConnection url 等等 但我必须从多个线程访问数据库 所以我必须使用连接池 问题1 是 com mysql
  • 为什么是 javascript:history.go(-1);无法在移动设备上工作?

    首先 一些背景 我有一个向用户呈现搜索页面 html 表单 的应用程序 填写标准并单击 搜索 按钮后 结果将显示在标准部分下方 在结果列表中 您可以通过单击将您带到新页面的链接来查看单个结果的详细信息 在详细信息页面中 我添加了一个 返回结
  • Android 构建发布失败,原因为:java.lang.ArrayIndexOutOfBoundsException:213(pr​​oguard 问题)

    我的项目使用调试构建变体构建得很好 但使用发布变体 Android Studio 会抛出 引起原因 java lang ArrayIndexOutOfBoundsException 213 可能是什么问题 如果我设置minifyEnable
  • okhttp 获取失败响应

    我已经在我的 android 客户端中实现了 okhttp 来进行网络调用 当我收到失败响应时 我会收到失败代码以及与该代码相关的文本作为消息 但我没有收到服务器发送给我的自定义失败响应 在我实施的代码中的失败响应中 我收到的消息只是 错误
  • Android 中如何通过彩信发送图片?

    我正在开发多媒体应用程序 我正在通过相机捕获一张图像 并希望将该图像和文本发送到其他号码 但我不知道如何通过彩信发送图像 MMS 只是一个 http post 请求 您应该使用执行请求额外的网络功能 final ConnectivityMa
  • 使用 AsyncTask 传递值

    我一直在努力解决这个问题 但我已经到了不知道该怎么办的地步 我想做的是使用一个类下载文件并将其解析为字符串 然后将该字符串发送到另一个类来解析 JSON 内容 所有部件都可以单独工作 并且我已经单独测试了所有部件 我只是不知道如何将值发送到
  • 找不到符号 NOTIFICATION_SERVICE?

    package com test app import android app Notification import android app NotificationManager import android app PendingIn
  • 插件“Android Bundle Support”不兼容

    大家好 自从上次更新以来 当我启动 android studio 时 我遇到了一个非常奇怪的错误 我有这个错误 插件错误 插件 Android Bundle Support 不兼容 直到构建 AI 195 SNAPSHOT 我在网上找不到任
  • 没有支持 FEATURE_CAMERA_EXTERNAL 的 Android 设备

    根据this doc https source android com devices camera external usb cameras一些 Android 设备允许使用 Camera2 API 访问外部 USB 摄像头 我检查了大约
  • Android 后台倒计时器

    我有一个 Android 应用程序 它管理一个倒计时器 类 CountDownTimer 它显示在应用程序屏幕中 以显示到达 00 00 还剩多少时间 我现在的问题是 当我按主页按钮或启动另一个应用程序时 应用程序 计时器不会在后台运行 所
  • 发布的 Android apk 出现错误“包文件未正确签名”

    我最近将我的应用程序上传到 Android 市场 但是由于错误 下载时它拒绝运行 包文件未正确签名 我首先使用 eclipse 发布了数据包 右键单击导出 创建密钥库然后发布 但它拒绝工作 然后我下载了 keytool 和 jarsigne
  • Android 屏幕方向错误

    我使用的是 Android HTC HERO 2 1 版本 我写的活动

随机推荐