Reputation: 5111
I have the following code:
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,
),
)
],
),
),
),
),
);
}
}
When the handle is dragged, the image should rotate accordingly. But as you can see it's not working correctly. If I don't use Stack
and Positioned
, it works fine. But I do need Stack
and Positioned
. Please help me with this.
I am expecting the rotation to be like:
Upvotes: 3
Views: 2378
Reputation: 3383
Adding a fixed height and width to the stack fixes the issue and it is rotating correctly as you can see below.
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,
),
)
],
),
),
);
}
}
Upvotes: 7
Reputation: 629
I think this could be your solution and here is the demo https://dartpad.dartlang.org/dart.
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,
),
),
);
},
),
)
],
),
),
);
}
}
Upvotes: 0