Flutter 如何在基于手势检测手柄的颤振中旋转图像?

Flutter 如何在基于手势检测手柄的颤振中旋转图像?,flutter,dart,Flutter,Dart,我有以下代码: import 'package:flutter/material.dart'; double ballRadius = 7.5; void main() => runApp(MyApp()); class MyApp extends StatefulWidget { @override _MyAppState createState() => _MyAppState(); } class _MyAppState extends State<MyA

我有以下代码:

import 'package:flutter/material.dart';

double ballRadius = 7.5;

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

class MyApp extends StatefulWidget {
  @override
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  double finalAngle = 0.0;
  double oldAngle = 0.0;
  double upsetAngle = 0.0;

  double _height = 200;
  double _width = 300;

  Offset centerOfGestureDetector = Offset(ballRadius, ballRadius);

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      home: Scaffold(
        body: SafeArea(
          child: // rotate
              Transform.rotate(
            angle: finalAngle,
            child: Stack(
              children: [
                Positioned(
                  top: 50,
                  left: 50 + _width / 2,
                  child: Column(
                    children: [
                      GestureDetector(
                        behavior: HitTestBehavior.translucent,
                        onPanStart: (details) {
                          final touchPositionFromCenter =
                              details.localPosition - centerOfGestureDetector;
                          upsetAngle =
                              oldAngle - touchPositionFromCenter.direction;
                        },
                        onPanEnd: (details) {
                          setState(
                            () {
                              oldAngle = finalAngle;
                            },
                          );
                        },
                        onPanUpdate: (details) {
                          final touchPositionFromCenter =
                              details.localPosition - centerOfGestureDetector;

                          setState(
                            () {
                              finalAngle = touchPositionFromCenter.direction +
                                  upsetAngle;
                            },
                          );
                        },
                        child: Container(
                          height: 2 * ballRadius,
                          width: 2 * ballRadius,
                          decoration: BoxDecoration(
                            color: Colors.white,
                            borderRadius: BorderRadius.circular(ballRadius),
                            border: Border.all(
                              width: 2,
                              color: Colors.blue,
                            ),
                          ),
                        ),
                      ),
                      Container(
                        height: 50,
                        width: 2,
                        color: Colors.blue,
                      ),
                    ],
                  ),
                ),
                Positioned(
                  top: 100,
                  left: 50,
                  child: Image.network(
                    "https://via.placeholder.com/300x200",
                    width: _width,
                    height: _height,
                    fit: BoxFit.fill,
                  ),
                )
              ],
            ),
          ),
        ),
      ),
    );
  }
}

导入“包装:颤振/材料.省道”;
双球半径=7.5;
void main()=>runApp(MyApp());
类MyApp扩展了StatefulWidget{
@凌驾
_MyAppState createState()=>\u MyAppState();
}
类MyAppState扩展了状态{
双尾声=0.0;
双oldAngle=0.0;
双上斜角=0.0;
双倍高度=200;
双倍宽度=300;
检测仪的偏移中心=偏移(球半径、球半径);
@凌驾
小部件构建(构建上下文){
返回材料PP(
debugShowCheckedModeBanner:false,
家:脚手架(
正文:安全区(
儿童://轮换
变换。旋转(
角度:最后一段,
子:堆栈(
儿童:[
定位(
前50名,
左:50+_宽/2,
子:列(
儿童:[
手势检测器(
行为:HitTestBehavior.transparent,
onPanStart:(详细信息){
从中心到最终接触位置=
details.localPosition-检测器的中心;
上坡=
oldAngle-从中心方向的接触位置;
},
onPanEnd:(详细信息){
设定状态(
() {
oldAngle=最终语言;
},
);
},
onPanUpdate:(详细信息){
从中心到最终接触位置=
details.localPosition-检测器的中心;
设定状态(
() {
finalange=触摸位置fromcenter.direction+
向上倾斜;
},
);
},
子:容器(
高度:2*球半径,
宽度:2*球半径,
装饰:盒子装饰(
颜色:颜色,白色,
边界半径:边界半径。圆形(球半径),
边界:边界(
宽度:2,
颜色:颜色,蓝色,
),
),
),
),
容器(
身高:50,
宽度:2,
颜色:颜色,蓝色,
),
],
),
),
定位(
前100名,
左:50,,
孩子:Image.network(
"https://via.placeholder.com/300x200",
宽度:_宽度,
高度:_高度,
fit:BoxFit.fill,
),
)
],
),
),
),
),
);
}
}
拖动控制柄时,图像应相应旋转。但正如你所看到的,它工作不正常。如果我不使用
堆栈
定位
,它可以正常工作。但我确实需要
堆栈
定位
。请帮我做这个

我期待着这样的轮换:


我认为这可能是您的解决方案,这是演示

import'dart:math';
进口“包装:颤振/材料.省道”;
void main(){
runApp(MyApp());
}
类MyApp扩展了无状态小部件{
@凌驾
小部件构建(构建上下文){
返回材料PP(
debugShowCheckedModeBanner:false,
主题:主题数据(
主样本:颜色。蓝色,
),
主页:RotateText(),
);
}
}
类RotateText扩展StatefulWidget{
RotateText({Key}):super(Key:Key);//已更改
@凌驾
_RotateTextState createState()=>_RotateTextState();
}
类_RotateTextState扩展状态{
双尾声=0.0;
@凌驾
小部件构建(构建上下文){
返回_defaultApp(上下文);
}
_defaultApp(构建上下文){
返回脚手架(
appBar:appBar(
标题:文本('单指旋转'),//已更改
),
正文:中(
子:列(
儿童:[
容器(
颜色:颜色,红色,
填充:边缘设置。全部(10),
页边距:仅限边缘集(顶部:50),
子对象:Transform.rotate(
角度:最后一段,
子:容器(
高度:100.0,
宽度:100.0,
孩子:Image.network(
'https://picsum.photos/250?image=9',
),
),
),
),
容器(
宽度:250,
身高:250,
颜色:颜色。灰色,
保证金:所有边缘套(30.0),
子:布局生成器(
生成器:(上下文、约束){
返回手势检测器(
行为:HitTestBehavior.transparent,
onPanUpdate:(详细信息){
检测仪的偏移中心=偏移(
constraints.maxWidth/2、constraints.maxHeight/2);
从中心到最终接触位置=
details.localPosition-检测器的中心;
打印(从中心方向的触摸位置*180/pi);
设定状态(
() {
最终语言=触摸POSI
import 'dart:math';

import 'package:flutter/material.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: RotateText(),
    );
  }
}

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

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

class _RotateTextState extends State<RotateText> {
  double finalAngle = 0.0;

  @override
  Widget build(BuildContext context) {
    return _defaultApp(context);
  }

  _defaultApp(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Single finger Rotation'), // changed
      ),
      body: Center(
        child: Column(
          children: <Widget>[
            Container(
              color: Colors.red,
              padding: EdgeInsets.all(10),
              margin: EdgeInsets.only(top: 50),
              child: Transform.rotate(
                angle: finalAngle,
                child: Container(
                  height: 100.0,
                  width: 100.0,
                  child: Image.network(
                    'https://picsum.photos/250?image=9',
                  ),
                ),
              ),
            ),
            Container(
              width: 250,
              height: 250,
              color: Colors.grey,
              margin: EdgeInsets.all(30.0),
              child: LayoutBuilder(
                builder: (context, constraints) {
                  return GestureDetector(
                    behavior: HitTestBehavior.translucent,
                    onPanUpdate: (details) {
                      Offset centerOfGestureDetector = Offset(
                          constraints.maxWidth / 2, constraints.maxHeight / 2);
                      final touchPositionFromCenter =
                          details.localPosition - centerOfGestureDetector;
                      print(touchPositionFromCenter.direction * 180/pi);
                      setState(
                            () {
                          finalAngle = touchPositionFromCenter.direction;
                        },
                      );
                    },
                    child: Transform.rotate(
                      angle: finalAngle,
                      child: Icon(
                        Icons.arrow_forward,
                        color: Colors.white,
                        size: 200,
                      ),
                    ),
                  );
                },
              ),
            )
          ],
        ),
      ),
    );
  }
}

import 'package:flutter/material.dart';

double ballRadius = 7.5;

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

class MyApp extends StatefulWidget {
  @override
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  double finalAngle = 0.0;
  double oldAngle = 0.0;
  double upsetAngle = 0.0;

  double _height = 200;
  double _width = 300;

  Offset centerOfGestureDetector = Offset(ballRadius, ballRadius);

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      home: Scaffold(
        body: SafeArea(
          child: // rotate
          Stack(
            children: [
              getImageWithHandle(),
            ],
          ),
        ),
      ),
    );
  }
  
  
  Widget getImageWithHandle(){
    return Transform.rotate(
                  angle: finalAngle,
                  child: SizedBox(
                    height: 400,
                    width: 400,
                    child: Stack(
                      children: [
                        Positioned(
                          top: 50,
                          left: 50 + _width / 2,
                          child: Column(
                            mainAxisSize: MainAxisSize.min,
                            children: [
                              GestureDetector(
                                behavior: HitTestBehavior.translucent,
                                onPanStart: (details) {
                                  final touchPositionFromCenter =
                                      details.localPosition - centerOfGestureDetector;
                                  upsetAngle =
                                      oldAngle - touchPositionFromCenter.direction;
                                },
                                onPanEnd: (details) {
                                  setState(
                                        () {
                                      oldAngle = finalAngle;
                                    },
                                  );
                                },
                                onPanUpdate: (details) {
                                  final touchPositionFromCenter =
                                      details.localPosition - centerOfGestureDetector;

                                  setState(
                                        () {
                                      finalAngle = touchPositionFromCenter.direction +
                                          upsetAngle;
                                    },
                                  );
                                },
                                child: Container(
                                  height: 2 * ballRadius,
                                  width: 2 * ballRadius,
                                  decoration: BoxDecoration(
                                    color: Colors.white,
                                    borderRadius: BorderRadius.circular(ballRadius),
                                    border: Border.all(
                                      width: 2,
                                      color: Colors.blue,
                                    ),
                                  ),
                                ),
                              ),
                              Container(
                                height: 50,
                                width: 2,
                                color: Colors.blue,
                              ),
                            ],
                          ),
                        ),
                        Positioned(
                          top: 100,
                          left: 50,
                          child: Image.network(
                            "https://via.placeholder.com/300x200",
                            width: _width,
                            height: _height,
                            fit: BoxFit.fill,
                          ),
                        )
                      ],
                    ),
                  ),
                );
  }
}