Flutter: after rotate widget inside stack, when changing the position it is move wrong direction

969 views Asked by At

i try to rotate the widget and then try to move around, it moves into different direction.

I'm realize, I need another calculation to normalize the position when its move, with condition rotate more than zero , but I don't know how, if anyone can help, thank you this is my code.

import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      debugShowCheckedModeBanner: false,
      home: const TestingDesign2(),
    );
  }
}

class TestingDesign2 extends StatefulWidget {
  const TestingDesign2({super.key});

  @override
  State<TestingDesign2> createState() => _TestingDesign2State();
}

class _TestingDesign2State extends State<TestingDesign2> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(title: Text("Testing")),
        body: Container(
          color: Colors.blueAccent.withOpacity(0.5),
          child: Stack(
            alignment: Alignment.center,
            // clipBehavior: Clip.none,
            children: [ItemTesting()],
          ),
        ));
  }
}

class ItemTesting extends StatefulWidget {
  const ItemTesting({super.key});

  @override
  State<ItemTesting> createState() => _ItemTestingState();
}

class _ItemTestingState extends State<ItemTesting> {
  double rotation = 0;
  Size size = Size(300, 300);
  Offset position = Offset(10, 10);
  double offsetAngle = 0;
  bool isRotate = false;

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

  Widget _Item() {
    return Positioned(
      left: position.dx,
      top: position.dy,
      child: Transform.rotate(
        angle: rotation,
        child: SizedBox(
          height: size.height,
          width: size.width,
          child: Stack(
            children: [
              GestureDetector(
                onPanStart: onPanStart,
                onPanUpdate: onPanUpdate,
                onPanEnd: (details) {
                  isRotate = false;
                },
                onPanCancel: () {
                  isRotate = false;
                },
                child: Container(
                  color: Colors.red,
                  height: size.height,
                  width: size.width,
                ),
              ),
              IgnorePointer(
                child: Align(
                  alignment: Alignment.topRight,
                  child: ClipOval(
                      child: Container(
                    height: 25,
                    width: 25,
                    color: Colors.blue,
                  )),
                ),
              ),
            ],
          ),
        ),
      ),
    );
  }

  onPanStart(details) {
    Offset centerOfGestureDetector = Offset(size.width / 2, size.height / 2);
    final touchPositionFromCenter =
        details.localPosition - centerOfGestureDetector;
    offsetAngle = touchPositionFromCenter.direction - rotation;
    // top right
    if (details.localPosition.dx > (size.width - 25) &&
        details.localPosition.dy <= 25) {
      isRotate = true;
    }
  }

  onPanUpdate(details) {
    if (isRotate) {
      Offset centerOfGestureDetector = Offset(size.width / 2, size.height / 2);
      final touchPositionFromCenter =
          details.localPosition - centerOfGestureDetector;
      // print(touchPositionFromCenter.direction * 180 / math.pi);

      rotation = touchPositionFromCenter.direction - offsetAngle;
    } else {
      position = new Offset(
          position.dx + details.delta.dx, position.dy + details.delta.dy);
    }
    setState(() {});
  }
}

enter image description here

https://dartpad.dev/?id=1403cd7c7a121a7b26d6b6c3ab422cf0

1

There are 1 answers

0
mamena tech On BEST ANSWER

Finally, I managed to make a widget that can be rotated and moved without moving in the wrong direction after rotated.

this is the code

import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      debugShowCheckedModeBanner: false,
      home: const TestingDesign2(),
    );
  }
}



class TestingDesign2 extends StatefulWidget {
  const TestingDesign2({super.key});

  @override
  State<TestingDesign2> createState() => _TestingDesign2State();
}

class _TestingDesign2State extends State<TestingDesign2> {
  Size size = Size(200, 200);

  var keyItem = GlobalKey();

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(title: Text("Testing design 2")),
        body: Container(
          color: Colors.blueAccent.withOpacity(0.5),
          // key: keyContainer,
          child: Stack(
            alignment: Alignment.center,
            // clipBehavior: Clip.none,
            children: [ItemTesting(key: keyItem, keyItem: keyItem)],
          ),
        ));
  }
}

class ItemTesting extends StatefulWidget {
  var keyItem;
  ItemTesting({super.key, required this.keyItem});

  @override
  State<ItemTesting> createState() => _ItemTestingState();
}

class _ItemTestingState extends State<ItemTesting> {
  double rotation = 0;
  Size size = Size(300, 300);
  Offset position = Offset(10, 10);
  double offsetAngle = 0;
  bool isRotate = false;

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

  Widget _Item() {
    return Positioned(
      left: position.dx,
      top: position.dy,
      child: Transform.rotate(
        angle: rotation,
        child: SizedBox(
          height: size.height,
          width: size.width,
          child: Stack(
            children: [
              GestureDetector(
                onPanStart: onPanStart,
                onPanUpdate: onPanUpdate,
                behavior: HitTestBehavior.translucent,
                onPanEnd: (details) {
                  isRotate = false;
                },
                onPanCancel: () {
                  isRotate = false;
                },
                child: Container(
                  color: Colors.red,
                  height: size.height,
                  width: size.width,
                ),
              ),
              IgnorePointer(
                child: Align(
                  alignment: Alignment.topRight,
                  child: ClipOval(
                      child: Container(
                    height: 25,
                    width: 25,
                    color: Colors.blue,
                  )),
                ),
              ),
         
            ],
          ),
        ),
      ),
    );
  }

  

  var touchPosition = Offset.zero;
  onPanStart(DragStartDetails details) {
    Offset centerOfGestureDetector = Offset(size.width / 2, size.height / 2);
    final touchPositionFromCenter =
        details.localPosition - centerOfGestureDetector;
    offsetAngle = touchPositionFromCenter.direction - rotation;

    final RenderBox referenceBox =
        widget.keyItem.currentContext.findRenderObject();
    var x = referenceBox.globalToLocal(details.globalPosition);

    touchPosition = Offset(x.dx, x.dy + 55);
    // top right
    if (details.localPosition.dx > (size.width - 25) &&
        details.localPosition.dy <= 25) {
      isRotate = true;
    }
  }

  onPanUpdate(DragUpdateDetails details) {
    if (isRotate) {
      Offset centerOfGestureDetector = Offset(size.width / 2, size.height / 2);
      final touchPositionFromCenter =
          details.localPosition - centerOfGestureDetector;

      rotation = touchPositionFromCenter.direction - offsetAngle;
    } else {
      var positionG = position + details.globalPosition;
      var positiong2 = positionG - touchPosition;
      position = (positiong2 - position);
    }
    setState(() {});
  }
}