Let an object move with AnimatedPositioned - flutter

I asked this question in this link Transition with futter move object
how i can make movig an object with AnimatedPositioned ? if i want an object move with a value = 1, or a value = 10
or something like that:
i = 0;
i++;
or
i = 0;
i = i + 10;
how i can do that with AnimatedPositioned

You only need to update position value from your AnimatedPositioned:
AnimatedPositioned(
width: selected ? 200.0 : 50.0,
height: selected ? 50.0 : 200.0,
top: selected ? 50.0 : 150.0,
duration: const Duration(seconds: 2),
curve: Curves.fastOutSlowIn,
child: GestureDetector(
onTap: () {
setState(() {
selected = !selected;
});
},
child: Container(
color: Colors.blue,
child: const Center(child: Text('Tap me')),
),
),
)
Just change that values to yours.
Full example:
import 'package:flutter/material.dart';
void main() => runApp(const MyApp());
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
static const String _title = 'Flutter Code Sample';
#override
Widget build(BuildContext context) {
return MaterialApp(
title: _title,
home: Scaffold(
appBar: AppBar(title: const Text(_title)),
body: const Center(
child: MyStatefulWidget(),
),
),
);
}
}
class MyStatefulWidget extends StatefulWidget {
const MyStatefulWidget({Key? key}) : super(key: key);
#override
State<MyStatefulWidget> createState() => _MyStatefulWidgetState();
}
class _MyStatefulWidgetState extends State<MyStatefulWidget> {
bool selected = false;
#override
Widget build(BuildContext context) {
return SizedBox(
width: 200,
height: 350,
child: Stack(
children: <Widget>[
AnimatedPositioned(
width: selected ? 200.0 : 50.0,
height: selected ? 50.0 : 200.0,
top: selected ? 50.0 : 150.0,
duration: const Duration(seconds: 2),
curve: Curves.fastOutSlowIn,
child: GestureDetector(
onTap: () {
setState(() {
selected = !selected;
});
},
child: Container(
color: Colors.blue,
child: const Center(child: Text('Tap me')),
),
),
),
],
),
);
}
}
Info: https://api.flutter.dev/flutter/widgets/AnimatedPositioned-class.html

Related

AnimatedPositioned - how to change position automatically without pressing button

i want to use the animated positioned class to change widget position with the launch of the screen without pressing a button!
class MyStatefulWidget extends StatefulWidget {
const MyStatefulWidget({Key? key}) : super(key: key);
#override
State<MyStatefulWidget> createState() => _MyStatefulWidgetState();
}
class _MyStatefulWidgetState extends State<MyStatefulWidget> {
bool selected = false;
#override
Widget build(BuildContext context) {
return SizedBox(
width: 200,
height: 350,
child: Stack(
children: <Widget>[
AnimatedPositioned(
width: selected ? 200.0 : 50.0,
height: selected ? 50.0 : 200.0,
top: selected ? 50.0 : 150.0,
duration: const Duration(seconds: 2),
curve: Curves.fastOutSlowIn,
child: GestureDetector(
onTap: () {
setState(() {
selected = !selected;
});
},
child: Container(
color: Colors.blue,
child: const Center(child: Text('Tap me')),
),
),
),
],
),
);
}
}
i tried to change it by using a WidgetsBinding like this :
WidgetsBinding.instance.addPostFrameCallback((_) {
setState(() {
selected = true;
});
print(' widget binding : $selected');
});
it works fine but the problem was that it doesnt excuted once, it keeps running and change the value to true! like this :
I copy/past the code you have shared to see what's going on, and it's working just fine for me. I have this code
import 'package:flutter/material.dart';
void main() async {
return runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return const MaterialApp(
home: Scaffold(
body: MyStatefulWidget(),
),
);
}
}
class MyStatefulWidget extends StatefulWidget {
const MyStatefulWidget({Key? key}) : super(key: key);
#override
State<MyStatefulWidget> createState() => _MyStatefulWidgetState();
}
class _MyStatefulWidgetState extends State<MyStatefulWidget> {
#override
void initState() {
super.initState();
WidgetsBinding.instance.addPostFrameCallback((_) {
setState(() {
selected = true;
});
print(' widget binding : $selected');
});
}
bool selected = false;
#override
Widget build(BuildContext context) {
return SizedBox(
width: 200,
height: 350,
child: Stack(
children: <Widget>[
AnimatedPositioned(
width: selected ? 200.0 : 50.0,
height: selected ? 50.0 : 200.0,
top: selected ? 50.0 : 150.0,
duration: const Duration(seconds: 2),
curve: Curves.fastOutSlowIn,
child: GestureDetector(
onTap: () {
setState(() {
selected = !selected;
});
},
child: Container(
color: Colors.blue,
child: const Center(child: Text('Tap me')),
),
),
),
],
),
);
}
}
The animation is run only once, when the postFrameCallback is called. The problem must be elsewhere

How to create interactive flowchart in flutter

I want to create a flutter UI where there are some shapes like square, rectangle, circle, arrow. And I must be able to drag and drop them at the centre and add text to it and connect them. I have just started with flutter so I am not sure how to do this. Can anyone please help me?
Use Draggable class
Example:
import 'package:flutter/material.dart';
void main() => runApp(const MyApp());
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
static const String _title = 'Flutter Code Sample';
#override
Widget build(BuildContext context) {
return MaterialApp(
title: _title,
home: Scaffold(
appBar: AppBar(title: const Text(_title)),
body: const MyStatefulWidget(),
),
);
}
}
class MyStatefulWidget extends StatefulWidget {
const MyStatefulWidget({Key? key}) : super(key: key);
#override
State<MyStatefulWidget> createState() => _MyStatefulWidgetState();
}
class _MyStatefulWidgetState extends State<MyStatefulWidget> {
int acceptedData = 0;
#override
Widget build(BuildContext context) {
return Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
Draggable<int>(
// Data is the value this Draggable stores.
data: 10,
feedback: Container(
color: Colors.deepOrange,
height: 100,
width: 100,
child: const Icon(Icons.directions_run),
),
childWhenDragging: Container(
height: 100.0,
width: 100.0,
color: Colors.pinkAccent,
child: const Center(
child: Text('Child When Dragging'),
),
),
child: Container(
height: 100.0,
width: 100.0,
color: Colors.lightGreenAccent,
child: const Center(
child: Text('Draggable'),
),
),
),
DragTarget<int>(
builder: (
BuildContext context,
List<dynamic> accepted,
List<dynamic> rejected,
) {
return Container(
height: 100.0,
width: 100.0,
color: Colors.cyan,
child: Center(
child: Text('Value is updated to: $acceptedData'),
),
);
},
onAccept: (int data) {
setState(() {
acceptedData += data;
});
},
),
],
);
}
}

Flutter: how can I implement an animated Container from left to right?

I implement a Room Chat Screen and inside it an animated Container move from left to right and start a again after finish, could someone inform me how to implement it
You need looping animate container, then you can try some Marquee package, such as fast_marquee:
Marquee(
text: 'Some sample text that takes some space.',
style: TextStyle(color: Colors.blue, fontWeight: FontWeight.bold),
velocity: 100,
blankSpace: 10,
startPadding: 10,
reverse: true,
bounce: true,
startAfter: const Duration(seconds: 2),
pauseAfterRound: const Duration(seconds: 1),
numberOfRounds: 5,
showFadingOnlyWhenScrolling: false,
fadingEdgeStartFraction: 0.05,
fadingEdgeEndFraction: 0.05,
curve: Curves.easeInOut,
)
OR
try AnimatedPositioned:
import 'package:flutter/material.dart';
void main() => runApp(const MyApp());
/// This is the main application widget.
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
static const String _title = 'Flutter Code Sample';
#override
Widget build(BuildContext context) {
return MaterialApp(
title: _title,
home: Scaffold(
appBar: AppBar(title: const Text(_title)),
body: const Center(
child: MyStatefulWidget(),
),
),
);
}
}
/// This is the stateful widget that the main application instantiates.
class MyStatefulWidget extends StatefulWidget {
const MyStatefulWidget({Key? key}) : super(key: key);
#override
State<MyStatefulWidget> createState() => _MyStatefulWidgetState();
}
/// This is the private State class that goes with MyStatefulWidget.
class _MyStatefulWidgetState extends State<MyStatefulWidget> {
bool selected = false;
#override
Widget build(BuildContext context) {
return SizedBox(
width: 200,
height: 350,
child: Stack(
children: <Widget>[
AnimatedPositioned(
width: selected ? 200.0 : 50.0,
height: selected ? 50.0 : 200.0,
top: selected ? 50.0 : 150.0,
duration: const Duration(seconds: 2),
curve: Curves.fastOutSlowIn,
child: GestureDetector(
onTap: () {
setState(() {
selected = !selected;
});
},
child: Container(
color: Colors.blue,
child: const Center(child: Text('Tap me')),
),
),
),
],
),
);
}
}

Access values in flutter

How can I access a variable value from one stateful widget class to another stateful widget class. Also both widget classes are in different .dart files.
This is screen.dart having the variable "List points". I want to use it in home.dart.
class Draw extends StatefulWidget {
const Draw({Key? key}) : super(key: key);
#override
_DrawState createState() => _DrawState();
}
class _DrawState extends State<Draw> {
List points = [];
#override
Widget build(BuildContext context) {
return GestureDetector(
onPanUpdate: (DragUpdateDetails details) {
Offset localPos = details.localPosition;
setState(() {
if (localPos.dx >= 0 &&
localPos.dx <= MediaQuery.of(context).size.width * 0.8 &&
localPos.dy >= 0 &&
localPos.dy <= MediaQuery.of(context).size.height * 0.5)
points.add(localPos);
else {
points.add(null);
}
});
},
onPanEnd: (DragEndDetails details) {
points.add(null);
},
child: CustomPaint(
painter: Painter(points: points),
),
);
}
}
...rest of code
This is home.dart
class Home extends StatefulWidget {
const Home({Key? key}) : super(key: key);
#override
_HomeState createState() => _HomeState();
}
class _HomeState extends State<Home> {
#override
Widget build(BuildContext context) {
return Scaffold(
floatingActionButton: FloatingActionButton(
backgroundColor: Colors.yellowAccent,
onPressed: () {
setState(() {
});
},
child: Icon(
Icons.restore_page,
color: Colors.black,
),
),
backgroundColor: Colors.grey[300],
appBar: AppBar(
backgroundColor: Colors.yellowAccent,
title: Text(
"Digit Recognizer",
style: TextStyle(color: Colors.black),
),
centerTitle: true,
),
body: Center(
child: Column(
children: [
SizedBox(
height: 15,
),
Container(
height: MediaQuery.of(context).size.height * 0.5,
width: MediaQuery.of(context).size.width * 0.8,
decoration: BoxDecoration(
color: Colors.white, border: Border.all(color: Colors.black)),
child: Draw(),
),
...rest of code
I want to access the "points" from screen.dart variable inside the floatingActionButton's on pressed() function in home.dart.
You can place both of these widgets in the same file and then create points as a global Variable, so
List points = [];
class Home extends StatefulWidget {
const Home({Key? key}) : super(key: key);
#override
_HomeState createState() => _HomeState();
}
class _HomeState extends State<Home> {
#override
Widget build(BuildContext context) {
return Scaffold(
floatingActionButton: FloatingActionButton(
backgroundColor: Colors.yellowAccent,
onPressed: () {
setState(() {
print(points);
});
},
child: Icon(
Icons.restore_page,
color: Colors.black,
),
),
backgroundColor: Colors.grey[300],
appBar: AppBar(
backgroundColor: Colors.yellowAccent,
title: Text(
"Digit Recognizer",
style: TextStyle(color: Colors.black),
),
centerTitle: true,
),
body: Center(
child: Column(
children: [
SizedBox(
height: 15,
),
Container(
height: MediaQuery.of(context).size.height * 0.5,
width: MediaQuery.of(context).size.width * 0.8,
decoration: BoxDecoration(
color: Colors.white, border: Border.all(color: Colors.black)),
child: Draw(),
),
...rest of code
class Draw extends StatefulWidget {
const Draw({Key? key}) : super(key: key);
#override
_DrawState createState() => _DrawState();
}
class _DrawState extends State<Draw> {
#override
Widget build(BuildContext context) {
return GestureDetector(
onPanUpdate: (DragUpdateDetails details) {
Offset localPos = details.localPosition;
setState(() {
if (localPos.dx >= 0 &&
localPos.dx <= MediaQuery.of(context).size.width * 0.8 &&
localPos.dy >= 0 &&
localPos.dy <= MediaQuery.of(context).size.height * 0.5)
points.add(localPos);
else {
points.add(null);
}
});
},
onPanEnd: (DragEndDetails details) {
points.add(null);
},
child: CustomPaint(
painter: Painter(points: points),
),
);
}
}
...rest of code
Usually I would not even create a different statefulw idget for this case but I am guessing you are doing it for some other reason. Creating a global variable allows it to be accessed from anywhere\
A better way of implementing the first answer might be this but you'll have to see if it works.
class Home extends StatefulWidget {
const Home({Key? key}) : super(key: key);
#override
_HomeState createState() => _HomeState();
}
class _HomeState extends State<Home> {
Widget drawWidget = Container();
#override
void initState(){
super.initState();
drawWidget = Draw();
}
#override
Widget build(BuildContext context) {
return Scaffold(
floatingActionButton: FloatingActionButton(
backgroundColor: Colors.yellowAccent,
onPressed: () {
setState(() {
print(drawWidget.points);
});
},
child: Icon(
Icons.restore_page,
color: Colors.black,
),
),
backgroundColor: Colors.grey[300],
appBar: AppBar(
backgroundColor: Colors.yellowAccent,
title: Text(
"Digit Recognizer",
style: TextStyle(color: Colors.black),
),
centerTitle: true,
),
body: Center(
child: Column(
children: [
SizedBox(
height: 15,
),
Container(
height: MediaQuery.of(context).size.height * 0.5,
width: MediaQuery.of(context).size.width * 0.8,
decoration: BoxDecoration(
color: Colors.white, border: Border.all(color: Colors.black)),
child: drawWidget,
),
...rest of code
And in drawWidget
class Draw extends StatefulWidget {
const Draw({Key? key}) : super(key: key);
List points = [];
#override
_DrawState createState() => _DrawState();
}
class _DrawState extends State<Draw> {
#override
Widget build(BuildContext context) {
return GestureDetector(
onPanUpdate: (DragUpdateDetails details) {
Offset localPos = details.localPosition;
setState(() {
if (localPos.dx >= 0 &&
localPos.dx <= MediaQuery.of(context).size.width * 0.8 &&
localPos.dy >= 0 &&
localPos.dy <= MediaQuery.of(context).size.height * 0.5)
widget.points.add(localPos);
else {
widget.points.add(null);
}
});
},
onPanEnd: (DragEndDetails details) {
widget.points.add(null);
},
child: CustomPaint(
painter: Painter(points: widget.points),
),
);
}
}
...rest of code
Hope it helps
The print statement in each code shows how to access
class stful1{
//create state method
}
class stful1 extends state{
//Widget build method
//data is actual data you want to send
Navigator.push(context,MaterialPageRoute((context)=>stful2(data)))
}
//stful2
class stful2{
//accept data in constructor
dataType data;
stful2(this.data);
//create state method
}
class stful2 extends state{
//Widget build method
//access like widget.data
}

How to have the drawer push the content instead of going on top of it?

I'm trying to build something similar to the slack app (see screenshot below) where the navigation drawer pushes the screen away instead of going on top.
I've been trying with the Drawer component without success. I've also looked at PageView but it seems that the children need to take 100% of the width.
Does someone have an idea of how to implement it?
EDIT
A similar result can be achieved with a Stack and AnimatedPositioned
class SlidingDrawer extends StatefulWidget {
final Widget drawer;
final Widget child;
final int swipeSensitivity;
final double drawerRatio;
final Color overlayColor;
final double overlayOpacity;
final int animationDuration;
final Curve animationCurve;
SlidingDrawer({
Key key,
#required this.drawer,
#required this.child,
this.swipeSensitivity = 25,
this.drawerRatio = 0.8,
this.overlayColor = Colors.black,
this.overlayOpacity = 0.5,
this.animationDuration = 500,
this.animationCurve = Curves.ease,
}) : super(key: key);
#override
_SlidingDrawerState createState() => _SlidingDrawerState();
}
class _SlidingDrawerState extends State<SlidingDrawer> {
bool _opened = false;
void open() {
setState(() {
_opened = true;
});
}
void close() {
setState(() {
_opened = false;
});
}
#override
Widget build(BuildContext context) {
final width = MediaQuery.of(context).size.width;
final height = MediaQuery.of(context).size.height;
final drawerWidth = width * widget.drawerRatio;
return GestureDetector(
onHorizontalDragUpdate: (details) {
if (details.delta.dx > widget.swipeSensitivity) {
open();
} else if (details.delta.dx < -widget.swipeSensitivity) {
close();
}
},
child: SizedBox(
width: width,
height: height,
child: Stack(
children: [
AnimatedPositioned(
width: drawerWidth,
height: height,
left: _opened ? 0 : -drawerWidth,
duration: Duration(milliseconds: widget.animationDuration),
curve: widget.animationCurve,
child: Container(
color: Colors.amber,
child: widget.drawer,
),
),
AnimatedPositioned(
height: height,
width: width,
left: _opened ? drawerWidth : 0,
duration: Duration(milliseconds: widget.animationDuration),
curve: widget.animationCurve,
child: Stack(
fit: StackFit.expand,
children: [
widget.child,
AnimatedSwitcher(
duration: Duration(milliseconds: widget.animationDuration),
switchInCurve: widget.animationCurve,
switchOutCurve: widget.animationCurve,
child: _opened
? GestureDetector(
onTap: () {
setState(() {
_opened = false;
});
},
child: Container(
color: widget.overlayColor.withOpacity(
widget.overlayOpacity,
),
),
)
: null,
)
],
),
),
],
),
),
);
}
}
ORIGINAL ANSWER
As pointed out by #Yadu in the comment
you could use Single child horizontal scroll view (with disabled scroll physics) with Scrollable.ensureVisible(context) to show the menu
using an horizontal scroll view is working.
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
home: MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key}) : super(key: key);
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
bool _drawerOpened = false;
final drawerKey = new GlobalKey();
final mainKey = new GlobalKey();
#override
Widget build(BuildContext context) {
return SingleChildScrollView(
physics: NeverScrollableScrollPhysics(),
scrollDirection: Axis.horizontal,
child: Row(
children: [
Container(
key: drawerKey,
color: Colors.green,
width: MediaQuery.of(context).size.width * 0.8,
),
SizedBox(
key: mainKey,
width: MediaQuery.of(context).size.width,
height: MediaQuery.of(context).size.height,
child: Scaffold(
appBar: AppBar(
title: Text("My Page"),
leading: IconButton(
icon: Icon(Icons.menu),
onPressed: _toggleDrawer,
),
),
body: Container(
color: Colors.yellow,
width: MediaQuery.of(context).size.width,
),
),
),
],
),
);
}
void _toggleDrawer() {
setState(() {
_drawerOpened = !_drawerOpened;
});
if (_drawerOpened) {
Scrollable.ensureVisible(drawerKey.currentContext);
} else {
Scrollable.ensureVisible(mainKey.currentContext);
}
}
}