Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/flutter/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Flutter 颤振中的多向涡旋_Flutter_Flutter Layout - Fatal编程技术网

Flutter 颤振中的多向涡旋

Flutter 颤振中的多向涡旋,flutter,flutter-layout,Flutter,Flutter Layout,我来自web开发背景,并且习惯于能够创建一个x和y溢出的元素(允许向任何方向滚动)。我正在努力用flifter实现同样的功能 通过查看文档,我发现了SingleChildScrollView,但它只允许Axis.horizontal或Axis.vertical,不能同时允许两者 因此,我尝试了以下方法: return SingleChildScrollView( // horizontal scroll widget scrollDirection: Axis.horizontal,

我来自web开发背景,并且习惯于能够创建一个x和y溢出的元素(允许向任何方向滚动)。我正在努力用flifter实现同样的功能

通过查看文档,我发现了SingleChildScrollView,但它只允许Axis.horizontal或Axis.vertical,不能同时允许两者

因此,我尝试了以下方法:

return SingleChildScrollView( // horizontal scroll widget
    scrollDirection: Axis.horizontal,
        child: SingleChildScrollView( // vertical scroll widget
            scrollDirection: Axis.vertical,
            child: ...content of the container etc...
        )
    );
这适用于x和y,但不允许对角滚动

有没有一种方法可以实现对角滚动,或者有没有更好的材质小部件我完全没有


谢谢

我已经找到了一个解决方案,尽管它并不完美:

我创建了一个带有
Offset\u scrollOffset
的StatefulWidget,它使用一个ClipRect和一个类型为Transform的子级。变换矩阵(
Matrix4.identity()…translate(\u offset.dx,\u offset.dy)
)应用于变换

gesturedector
有一个onPanUpdate回调,用于更新滚动位置<代码>\u scrollOffset+=e.delta。如果滚动位置太低或太高,只需设置滚动位置即可将其限制在小部件的边界上

动画和动画控制器用于设置投掷速度。onPanEnd提供了最后一次平移的速度,因此只需根据该速度执行一次二人之间的投掷

动画会在捕捉时停止,以便用户可以停止滚动速度

这方面的主要问题是它不能完美地模拟Android或iOS的滚动速度,尽管我正在努力使用Flatter提供的ScrollSimulation类使其工作得更好。

import'package:flatter/signatures.dart';
import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';

class FreeScrollView extends StatefulWidget {
  final Widget child;
  final ScrollPhysics physics;

  const FreeScrollView({Key? key, this.physics = const ClampingScrollPhysics(), required this.child}) : super(key: key);

  @override
  State<FreeScrollView> createState() => _FreeScrollViewState();
}

class _FreeScrollViewState extends State<FreeScrollView> {
  final ScrollController _verticalController = ScrollController();
  final ScrollController _horizontalController = ScrollController();
  final Map<Type, GestureRecognizerFactory> _gestureRecognizers = <Type, GestureRecognizerFactory>{};

  @override
  void initState() {
    super.initState();
    _gestureRecognizers[PanGestureRecognizer] = GestureRecognizerFactoryWithHandlers<PanGestureRecognizer>(
        () => PanGestureRecognizer(),
        (instance) => instance
          ..onDown = _handleDragDown
          ..onStart = _handleDragStart
          ..onUpdate = _handleDragUpdate
          ..onEnd = _handleDragEnd
          ..onCancel = _handleDragCancel
          ..minFlingDistance = widget.physics.minFlingDistance
          ..minFlingVelocity = widget.physics.minFlingVelocity
          ..maxFlingVelocity = widget.physics.maxFlingVelocity
          ..velocityTrackerBuilder = ScrollConfiguration.of(context).velocityTrackerBuilder(context)
          ..dragStartBehavior = DragStartBehavior.start);
  }

  @override
  Widget build(BuildContext context) => Stack(children: [
        SingleChildScrollView(
            scrollDirection: Axis.horizontal,
            controller: _horizontalController,
            physics: widget.physics,
            child: SingleChildScrollView(
                scrollDirection: Axis.vertical, // ignore: avoid_redundant_argument_values
                controller: _verticalController,
                physics: widget.physics,
                child: widget.child)),
        Positioned.fill(
            child: RawGestureDetector(
          gestures: _gestureRecognizers,
          behavior: HitTestBehavior.opaque,
          excludeFromSemantics: true,
        )),
      ]);

  Drag? _horizontalDrag;
  Drag? _verticalDrag;
  ScrollHoldController? _horizontalHold;
  ScrollHoldController? _verticalHold;

  void _handleDragDown(DragDownDetails details) {
    _horizontalHold = _horizontalController.position.hold(() => _horizontalHold = null);
    _verticalHold = _verticalController.position.hold(() => _verticalHold = null);
  }

  void _handleDragStart(DragStartDetails details) {
    _horizontalDrag = _horizontalController.position.drag(details, () => _horizontalDrag = null);
    _verticalDrag = _verticalController.position.drag(details, () => _verticalDrag = null);
  }

  void _handleDragUpdate(DragUpdateDetails details) {
    _horizontalDrag?.update(DragUpdateDetails(
        sourceTimeStamp: details.sourceTimeStamp,
        delta: Offset(details.delta.dx, 0),
        primaryDelta: details.delta.dx,
        globalPosition: details.globalPosition));
    _verticalDrag?.update(DragUpdateDetails(
        sourceTimeStamp: details.sourceTimeStamp,
        delta: Offset(0, details.delta.dy),
        primaryDelta: details.delta.dy,
        globalPosition: details.globalPosition));
  }

  void _handleDragEnd(DragEndDetails details) {
    _horizontalDrag
        ?.end(DragEndDetails(velocity: details.velocity, primaryVelocity: details.velocity.pixelsPerSecond.dx));
    _verticalDrag
        ?.end(DragEndDetails(velocity: details.velocity, primaryVelocity: details.velocity.pixelsPerSecond.dy));
  }

  void _handleDragCancel() {
    _horizontalHold?.cancel();
    _horizontalDrag?.cancel();
    _verticalHold?.cancel();
    _verticalDrag?.cancel();
  }
}
进口“包装:颤振/材料.省道”; 类FreeScrollView扩展StatefulWidget{ 最后一个孩子; 期末物理; const FreeScrollView({Key?Key,this.physics=const ClampingScrollPhysics(),需要this.child}):super(Key:Key); @凌驾 State createState()=>\u FreeScrollViewState(); } 类_FreeScrollViewState扩展状态{ 最终ScrollController_verticalController=ScrollController(); 最终ScrollController_horizontalController=ScrollController(); 最终地图_-gesturecognizers={}; @凌驾 void initState(){ super.initState(); _手势识别器[PanGestureRecognizer]=手势识别器工厂WithHandlers( ()=>PangestureRecognitor(), (实例)=>实例 …onDown=_handleDragDown …onStart=\u handleDragStart ..onUpdate=\u handleDragUpdate …onEnd=_handleDragEnd …onCancel=\u handledrag取消 ..minFlingDistance=widget.physics.minFlingDistance …minFlingVelocity=widget.physics.minFlingVelocity …maxFlingVelocity=widget.physics.maxFlingVelocity ..velocityTrackerBuilder=ScrollConfiguration.of(上下文)。velocityTrackerBuilder(上下文) ..dragStartBehavior=dragStartBehavior.start); } @凌驾 小部件构建(BuildContext上下文)=>堆栈(子项:[ SingleChildScrollView( 滚动方向:轴水平, 控制器:_水平控制器, 物理学:widget.physics, 子:SingleChildScrollView( scrollDirection:Axis.vertical,//忽略:避免冗余参数值 控制器:_垂直控制器, 物理学:widget.physics, child:widget.child), 定位填充( 孩子:RawGestureDetector( 手势:\手势识别器, 行为:HitTestBehavior.不透明, excludeFromSemantics:true, )), ]); 拖动?_水平拖动; 阻力?\垂直阻力; ScrollHoldController?\u水平保持; ScrollHoldController?\u垂直保持; void_handleDragDown(拖拽下细节){ _horizontalHold=_horizontalController.position.hold(()=>_horizontalHold=null); _verticalHold=\u verticalController.position.hold(()=>\u verticalHold=null); } void_handleDragStart(dragstart详细信息){ _horizontalDrag=\u horizontalController.position.drag(详细信息,()=>\u horizontalDrag=null); _verticalDrag=\u verticalController.position.drag(详细信息,()=>\u verticalDrag=null); } void\u handleDragUpdate(DragUpdate详细信息){ _水平拖动?更新(拖动更新详细信息( sourceTimeStamp:details.sourceTimeStamp, 增量:偏移量(details.delta.dx,0), primaryDelta:details.delta.dx, globalPosition:details.globalPosition); _垂直拖动?更新(拖动更新详细信息( sourceTimeStamp:details.sourceTimeStamp, 增量:偏移量(0,细节增量dy), primaryDelta:details.delta.dy, globalPosition:details.globalPosition); } void_handleDragEnd(图纸详图){ _水平阻力 ?结束(DragEndDetails(速度:details.velocity,primaryVelocity:details.velocity.pixelsPerSecond.dx)); _垂直阻力 ?.end(DragEndDetails(速度:details.velocity,primaryVelocity:details.velocity.pixelsPerSecond.dy)); } void_handleDragCancel(){ _水平保持?.cancel(); _水平拖动?.cancel(); _垂直保持?.cancel(); _垂直拖动?.cancel(); } }
InteractiveViewer是另一种选择,它支持对角拖动(而不是滚动)手势。