Flutter笔记:缩放手势

简介: Flutter笔记:缩放手势

Flutter笔记缩放手势


1. 概述

Flutter 中,缩放手势是一种常见的交互方式,它允许用户通过双指触摸屏幕来改变 UI 元素的大小。这种手势常用于查看图片、地图等场景中。本文接下来将先后介绍如何使用 GestureDetector 和更底层的 ScaleGestureRecognizer 各自实现缩放的代码如何写。

2. 缩放手势的识别和处理

在 Flutter 中,缩放手势的识别和处理主要依赖于 GestureDetector 组件。这个组件可以识别各种手势,包括缩放手势。

2.1 GestureDetector 组件

GestureDetector 组件有多个属性用于处理缩放,主要包括:

属性 描述
onScaleStart 当缩放手势开始时调用
onScaleUpdate 当缩放手势更新时调用
onScaleEnd 当缩放手势结束时调用

例如:

import 'package:flutter/material.dart';
void main() {
  runApp(const MyApp());
}
class MyApp extends StatelessWidget {
  const MyApp({super.key});
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: const Text('GestureDetector Example'),
        ),
        body: const Center(
          child: MyScale(),
        ),
      ),
    );
  }
}
class MyScale extends StatefulWidget {
  const MyScale({super.key});
  @override
  State<MyScale> createState() => _MyScaleState();
}
class _MyScaleState extends State<MyScale> {
  double _scale = 1.0;
  @override
  Widget build(BuildContext context) {
    return GestureDetector(
      onScaleStart: (ScaleStartDetails details) {
        print('缩放开始');
      },
      onScaleUpdate: (ScaleUpdateDetails details) {
        setState(() {
          _scale = details.scale;
        });
        print('缩放更新,当前缩放值:$_scale');
      },
      onScaleEnd: (ScaleEndDetails details) {
        print('缩放结束');
      },
      child: Transform.scale(
        scale: _scale,
        child: const FlutterLogo(size: 200),
      ),
    );
  }
}

上面的代码中,我们使用 GestureDetector 组件来识别缩放手势,并在 onScaleUpdate 回调函数中更新 _scale 变量的值。然后,我们使用 Transform.scale 组件来根据 _scale 的值来改变 Flutter Logo 的大小。其效果如下:

2.2 RawGestureDetector 和

RawGestureDetector 组件

使用 RawGestureDetectorScaleGestureRecognizer 也可以实现缩放手势。在大多数情况下,GestureDetector 组件已经足够用于处理缩放手势。然而,在一些的场景中我们可能需要更多的控制,这时就可以使用 ScaleGestureRecognizer 类。

const RawGestureDetector({
  Key? key,
  this.child,
  this.gestures = const <Type, GestureRecognizerFactory>{},
  this.behavior,
  this.excludeFromSemantics = false,
  this.semantics,
}) : super(key: key);

ScaleGestureRecognizer 类

ScaleGestureRecognizer 继承自 GestureRecognizer,是更底层的手势识别器,用于识别缩放手势。

ScaleGestureRecognizer 跟踪与屏幕接触的指针,并计算它们的焦点、指示的缩放级别和旋转。当建立一个焦点时,识别器会调用 onStart回调函数。随着焦点、缩放和旋转的变化,识别器会调用 onUpdate回调函数。当指针不再与屏幕接触时,识别器会调用 onEnd回调函数。

以下是 ScaleGestureRecognizer 的一些重要属性和方法:

  • onStart:当与屏幕接触的指针建立了焦点和初始缩放级别为1.0时调用。
  • onUpdate:当与屏幕接触的指针指示了新的焦点和/或缩放时调用。
  • onEnd:当指针不再与屏幕接触时调用。
  • addPointer:注册可能与此手势检测器相关的新指针。
  • addAllowedPointer:注册已经被此手势识别器允许的新指针。
  • dispose:释放由对象使用的任何资源。

ScaleGestureRecognizer 类的造函数如下:

ScaleGestureRecognizer({
  Object? debugOwner, // 用于在调试打印中识别手势识别器的对象。
  PointerDeviceKind? kind, // 此手势识别器应该处理的设备类型
  this.dragStartBehavior = DragStartBehavior.start, // 确定在所有涉及此手势的计算中,用作起点的点
})

其中:

  • kind:此手势识别器应该处理的设备类型。例如,如果 kind 设置为 PointerDeviceKind.mouse,那么这个手势识别器只会识别鼠标的手势。
  • dragStartBehavior:确定在所有涉及此手势的计算中,用作起点的点。默认值为 DragStartBehavior.start。

案例

下面是一个使用 RawGestureDetectorScaleGestureRecognizer 来识别和处理缩放和拖动手势的示例:

import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
void main() {
  runApp(const MyApp());
}
class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: const Text('GestureDetector Example'),
        ),
        body: const Center(
          child: MyWidget(),
        ),
      ),
    );
  }
}
class MyWidget extends StatefulWidget {
  const MyWidget({Key? key}) : super(key: key);
  @override
  State<MyWidget> createState() => _MyWidgetState();
}
class _MyWidgetState extends State<MyWidget> {
  final _scaleRecognizer = ScaleGestureRecognizer();
  double _scale = 1.0;
  Offset _panOffset = Offset.zero;
  @override
  void initState() {
    super.initState();
    _scaleRecognizer
      ..onStart = _handleScaleStart
      ..onUpdate = _handleScaleUpdate
      ..onEnd = _handleScaleEnd;
  }
  @override
  void dispose() {
    _scaleRecognizer.dispose();
    super.dispose();
  }
  @override
  Widget build(BuildContext context) {
    return RawGestureDetector(
      gestures: {
        ScaleGestureRecognizer:
            GestureRecognizerFactoryWithHandlers<ScaleGestureRecognizer>(
          () => _scaleRecognizer,
          (ScaleGestureRecognizer instance) {},
        ),
      },
      child: Transform.scale(
        scale: _scale,
        child: Transform.translate(
          offset: _panOffset,
          child: const FlutterLogo(size: 200),
        ),
      ),
    );
  }
  void _handleScaleStart(ScaleStartDetails details) {
    print('缩放开始');
  }
  void _handleScaleUpdate(ScaleUpdateDetails details) {
    setState(() {
      _scale = details.scale;
      _panOffset = details.localFocalPoint;
    });
    print('缩放更新,当前缩放值:$_scale');
    print('拖动更新,当前偏移值:$_panOffset');
  }
  void _handleScaleEnd(ScaleEndDetails details) {
    print('缩放结束');
  }
}

需要注意的是,使用 RawGestureDetector 比使用 GestureDetector 组件更复杂,需要手动管理手势的生命周期,包括创建、更新和释放手势。因此,除非你需要处理复杂的手势,否则通常推荐使用 GestureDetector 组件。

目录
打赏
0
0
0
0
332
分享
相关文章
|
6月前
|
Flutter笔记:手动配置VSCode中Dart代码自动格式化
Flutter笔记:手动配置VSCode中Dart代码自动格式化
776 5
|
6月前
|
Flutter笔记:谈Material状态属性-为什么FlatButton等旧版按钮就废弃了
Flutter笔记:谈Material状态属性-为什么FlatButton等旧版按钮就废弃了
128 4
Flutter笔记:关于WebView插件的用法(下)
Flutter笔记:关于WebView插件的用法(下)
369 5
|
6月前
|
Flutter笔记:Widgets Easier组件库(9)使用弹窗
Flutter笔记:Widgets Easier组件库(9)使用弹窗
162 3
Flutter笔记:Widgets Easier组件库-使用隐私守卫
Flutter笔记:Widgets Easier组件库-使用隐私守卫
79 2
|
6月前
|
Flutter笔记:Widgets Easier组件库(13)- 使用底部弹窗
Flutter笔记:Widgets Easier组件库(13)- 使用底部弹窗
142 2
|
6月前
|
Flutter笔记:Widgets Easier组件库(5)使用加减器
Flutter笔记:Widgets Easier组件库(5)使用加减器
171 2
|
6月前
|
Flutter笔记:Widgets Easier组件库(4)使用按钮组
Flutter笔记:Widgets Easier组件库(4)使用按钮组
50 2
|
6月前
|
Flutter笔记:Widgets Easier组件库(3)使用按钮组件
Flutter笔记:Widgets Easier组件库(3)使用按钮组件
123 2
Flutter笔记:关于WebView插件的用法(上)
Flutter笔记:关于WebView插件的用法(上)
2199 4

热门文章

最新文章

  • 1
    【11】flutter进行了聊天页面的开发-增加了即时通讯聊天的整体页面和组件-切换-朋友-陌生人-vip开通详细页面-即时通讯sdk准备-直播sdk准备-即时通讯有无UI集成的区别介绍-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
    11
  • 2
    【08】flutter完成屏幕适配-重建Android,增加GetX路由,屏幕适配,基础导航栏-多版本SDK以及gradle造成的关于fvm的使用(flutter version manage)-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
    35
  • 3
    【05】flutter完成注册页面完善样式bug-增加自定义可复用组件widgets-严格规划文件和目录结构-规范入口文件-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草央千澈
    3
  • 4
    【07】flutter完成主页-完成底部菜单栏并且做自定义组件-完整短视频仿抖音上下滑动页面-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草央千澈
    7
  • 5
    当flutter react native 等混开框架-并且用vscode-idea等编译器无法打包apk,打包安卓不成功怎么办-直接用android studio如何打包安卓apk -重要-优雅草卓伊凡
    4
  • 6
    零基础构建即时通讯开源项目OpenIM移动端-Flutter篇
    17
  • 7
    flutter3-dart3-dymall原创仿抖音(直播+短视频+聊天)商城app系统模板
    15
  • 8
    【09】flutter首页进行了完善-采用android studio 进行真机调试开发-增加了直播间列表和短视频人物列表-增加了用户中心-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
    11
  • 9
    【06】flutter完成注册页面-密码登录-手机短信验证-找回密码相关页面-并且实现静态跳转打包demo做演示-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草央千澈
    5
  • 10
    flutter开发中Use ‘const’ with the constructor to improve performance. Try adding the ‘const’ keyword to the constructor invocation.报错如何解决-优雅草卓伊凡
    4
  • 1
    【01】噩梦终结flutter配安卓android鸿蒙harmonyOS 以及next调试环境配鸿蒙和ios真机调试环境-flutter项目安卓环境配置-gradle-agp-ndkVersion模拟器运行真机测试环境-本地环境搭建-如何快速搭建android本地运行环境-优雅草卓伊凡-很多人在这步就被难倒了
    29
  • 2
    零基础构建即时通讯开源项目OpenIM移动端-Flutter篇
    59
  • 3
    flutter3-dart3-dymall原创仿抖音(直播+短视频+聊天)商城app系统模板
    42
  • 4
    【11】flutter进行了聊天页面的开发-增加了即时通讯聊天的整体页面和组件-切换-朋友-陌生人-vip开通详细页面-即时通讯sdk准备-直播sdk准备-即时通讯有无UI集成的区别介绍-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
    146
  • 5
    【09】flutter首页进行了完善-采用android studio 进行真机调试开发-增加了直播间列表和短视频人物列表-增加了用户中心-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
    40
  • 6
    当flutter react native 等混开框架-并且用vscode-idea等编译器无法打包apk,打包安卓不成功怎么办-直接用android studio如何打包安卓apk -重要-优雅草卓伊凡
    73
  • 7
    【08】flutter完成屏幕适配-重建Android,增加GetX路由,屏幕适配,基础导航栏-多版本SDK以及gradle造成的关于fvm的使用(flutter version manage)-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
    125
  • 8
    【07】flutter完成主页-完成底部菜单栏并且做自定义组件-完整短视频仿抖音上下滑动页面-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草央千澈
    75
  • 9
    flutter开发中Use ‘const’ with the constructor to improve performance. Try adding the ‘const’ keyword to the constructor invocation.报错如何解决-优雅草卓伊凡
    21
  • 10
    【06】flutter完成注册页面-密码登录-手机短信验证-找回密码相关页面-并且实现静态跳转打包demo做演示-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草央千澈
    30