I am trying to generate a list in flutter which delays every item after some delay.
I was tried using FutureBuilder and AnimatedList but i failed to get it.
import 'dart:async';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
void main(){
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Example(),
);
}
}
class Example extends StatefulWidget {
#override
_ExampleState createState() => new _ExampleState();
}
class _ExampleState extends State<Example> with TickerProviderStateMixin{
AnimationController listViewController;
final Animation listView;
Duration duration = new Duration(seconds: 3);
Timer _timer;
#override
void initState() {
listViewController = new AnimationController(
duration: new Duration(seconds: 2),
vsync: this
);
super.initState();
}
FlutterLogoStyle _logoStyle = FlutterLogoStyle.markOnly;
item() {
_timer = new Timer(const Duration(seconds: 1), () {
return Text("cdscs");
});
}
#override
void dispose() {
listViewController.dispose();
super.dispose();
}
#override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title: new Text("hello"),
),
// ListView Builder
body: AnimatedList(
initialItemCount: 10,
itemBuilder: (BuildContext context,
int index,
Animation<double> animation){
return item();
},
)
);
}
}
You could use the AnimationController and an Animation for every child like this example:
class Example extends StatefulWidget {
#override
_ExampleState createState() => new _ExampleState();
}
class _ExampleState extends State<Example> with TickerProviderStateMixin {
AnimationController _animationController;
double animationDuration = 0.0;
int totalItems = 10;
#override
void initState() {
super.initState();
final int totalDuration = 4000;
_animationController = AnimationController(
vsync: this, duration: new Duration(milliseconds: totalDuration));
animationDuration = totalDuration/(100*(totalDuration/totalItems));
_animationController.forward();
}
FlutterLogoStyle _logoStyle = FlutterLogoStyle.markOnly;
#override
void dispose() {
_animationController.dispose();
super.dispose();
}
#override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title: new Text("hello"),
),
// ListView Builder
body: ListView.builder(
itemCount: totalItems,
itemBuilder: (BuildContext context, int index) {
return new Item(index: index, animationController: _animationController, duration: animationDuration);
},
));
}
}
class Item extends StatefulWidget {
final int index;
final AnimationController animationController;
final double duration;
Item({this.index, this.animationController, this.duration});
#override
_ItemState createState() => _ItemState();
}
class _ItemState extends State<Item> {
Animation _animation;
double start;
double end;
#override
void initState() {
super.initState();
start = (widget.duration * widget.index ).toDouble();
end = start + widget.duration;
print("START $start , end $end");
_animation = Tween<double>(
begin: 0.0,
end: 1.0,
).animate(
CurvedAnimation(
parent: widget.animationController,
curve: Interval(
start,
end,
curve: Curves.easeIn,
),
),
)..addListener((){
setState(() {
});
});
}
#override
Widget build(BuildContext context) {
return Opacity(
opacity: _animation.value,
child: Padding(
padding: const EdgeInsets.all(8.0),
child: new Text("New Sample Item ${widget.index}"),
),
);
}
}
You can change the animation, in this case I was using opacity to simulate fade animation.
Maybe you can Check this response: https://stackoverflow.com/a/59121771/9481448
for (var i = 0; i < fetchedList.length; i++) {
future = future.then((_) {
return Future.delayed(Duration(milliseconds: 100), () {
// add/remove item
});
});
Related
I want to use AnimationController in the StatelessWidget class with Cubit or Bloc in a flutter, if anyone can help me with an example link to explain?
I think the general practice is to avoid using presentation layer components in Blocs. I would use Bloc to manage my state value, but run the animation components in a stateful widget.
Blocs
part 'side_bloc.freezed.dart';
typedef StateEmitter = Emitter<SideState>;
class SideBloc extends Bloc<SideEvent, SideState> {
SideBloc() : super(const SideState(20)) {
on<SideIncrement>(onIncrement);
on<SideDecrement>(onDecrement);
}
void onIncrement(SideIncrement event, StateEmitter emit) {
emit(state.copyWith(side: state.side + 10));
}
void onDecrement(SideDecrement event, StateEmitter emit) {
if (state.side <= 10) {
return;
}
emit(state.copyWith(side: state.side - 10));
}
}
#freezed
class SideEvent with _$SideEvent {
const factory SideEvent.increment() = SideIncrement;
const factory SideEvent.decrement() = SideDecrement;
}
#freezed
class SideState with _$SideState {
const factory SideState(int side) = _SideState;
}
Animated component
class HomePage extends StatefulWidget {
const HomePage({Key? key}) : super(key: key);
#override
State<HomePage> createState() => _HomePageState();
}
class _HomePageState extends State<HomePage>
with SingleTickerProviderStateMixin {
late AnimationController _controller;
late Animation<int> _animation;
late CurvedAnimation _curvedAnimation;
#override
void initState() {
_controller = AnimationController(
vsync: this,
duration: const Duration(seconds: 1),
);
_curvedAnimation = CurvedAnimation(
parent: _controller,
curve: Curves.elasticOut,
);
_animation = IntTween(begin: 20, end: 20).animate(_curvedAnimation);
_controller.forward();
super.initState();
}
#override
void dispose() {
_controller.dispose();
super.dispose();
}
void _animateTo(int value) {
int old = _animation.value;
_controller.reset();
_animation = IntTween(begin: old, end: value).animate(
_curvedAnimation,
);
_controller.forward();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Home'),
),
body: BlocListener<SideBloc, SideState>(
listener: (context, state) {
_animateTo(state.side);
},
child: AnimatedBuilder(
animation: _animation,
builder: (context, child) {
return SizedSquare(side: _animation.value);
},
),
),
floatingActionButton: const SideChangeButtons(),
);
}
}
class SideChangeButtons extends StatelessWidget {
const SideChangeButtons({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return Column(
mainAxisAlignment: MainAxisAlignment.end,
children: [
FloatingActionButton(
onPressed: () =>
context.read<SideBloc>().add(const SideEvent.increment()),
child: const Icon(Icons.add),
),
const SizedBox(height: 8),
FloatingActionButton(
onPressed: () =>
context.read<SideBloc>().add(const SideEvent.decrement()),
child: const Icon(Icons.remove),
),
],
);
}
}
class SizedSquare extends StatelessWidget {
final int side;
const SizedSquare({
Key? key,
required this.side,
}) : super(key: key);
#override
Widget build(BuildContext context) {
return Center(
child: SizedBox.fromSize(
size: Size.square(side.toDouble()),
child: Container(color: Colors.red),
),
);
}
}
AnimationController works with TickerProviderStateMixin which means that you MUST use a statefulWidget somewhere in your widget tree.
I have a problem with the animation, I want the heart to start small, increase and then decrease in size, as shown in the gif below.
Desired animation
But the current behavior is that the heart starts out big and then slows down.
Would anyone know what it would take to fix the animation?
Here is the flutter code:
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
home: MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage();
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> with SingleTickerProviderStateMixin {
Animation<double> _heartAnimation;
AnimationController _heartController;
#override
void dispose() {
_heartController.dispose();
super.dispose();
}
void _animate() {
_heartController
..reset()
..forward(from: 0.0)
..reverse(from: 1.0);
}
#override
void initState() {
super.initState();
final quick = const Duration(milliseconds: 500);
final scaleTween = Tween(begin: 0.0, end: 1.0);
_heartController = AnimationController(duration: quick, vsync: this);
_heartAnimation = scaleTween.animate(
CurvedAnimation(
parent: _heartController,
curve: Curves.elasticOut,
),
);
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: ScaleTransition(
scale: _heartAnimation,
child: Icon(Icons.favorite, size: 160.0, color: Colors.red),
)
),
floatingActionButton: FloatingActionButton(
onPressed: () {
_animate();
},
child: Icon(Icons.favorite_rounded),
),
);
}
}
Try this code, it works for me perfectly. If you have any questions please let know.
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(home: MyHomePage());
}
}
class MyHomePage extends StatefulWidget {
MyHomePage();
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> with SingleTickerProviderStateMixin {
Animation<double> animation;
AnimationController controller;
#override
void initState() {
super.initState();
final quick = const Duration(milliseconds: 500);
final scaleTween = Tween(begin: 0.0, end: 1.0);
controller = AnimationController(duration: quick, vsync: this);
animation = scaleTween.animate(
CurvedAnimation(
parent: controller,
curve: Curves.fastLinearToSlowEaseIn,
),
)..addListener(() {
setState(() => scale = animation.value);
});
}
#override
void dispose() {
controller.dispose();
super.dispose();
}
void _animate() {
animation
..addStatusListener((AnimationStatus status) {
if (scale == 1.0) {
controller.reverse();
}
});
controller.forward();
}
double scale = 0.0;
#override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Transform.scale(
scale: scale,
child: Icon(
Icons.favorite,
size: 160.0,
color: Colors.red
),
),
),
floatingActionButton: FloatingActionButton(
onPressed: () {
_animate();
},
child: Icon(Icons.favorite_rounded),
)
);
}
}
I'm trying to animate a container in a FutureBuilder widget which makes a request to a node js api on localhost. There seems to have no issues with the API, but I've noticed that the Container renders normally when I don't call controller.repeat(). i'm guessing that controller.repeat() doesn't work well asynchronously, but I haven't found any alternatives.
This is the code I've got so far:
class _HomeState extends State<Home> with SingleTickerProviderStateMixin {
AnimationController controller;
Animation<double> animation;
void initState() {
super.initState();
controller = AnimationController(
duration: const Duration(milliseconds: 3000), vsync: this);
animation = Tween<double>(begin: 10, end: 300).animate(controller);
animation.addListener(() {
setState(() {});
});
}
void dispose() {
controller.dispose();
super.dispose();
}
#override
Widget build(BuildContext context) {
final url = Uri.parse("http://localhost:8080");
return FutureBuilder(
future: http.get(url),
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.done) {
final themeList =
Map<String, dynamic>.from(jsonDecode(snapshot.data.body));
final keys = List.from(themeList.keys);
controller.repeat(); // Container shows when I comment this line out
return Center(
child: Container(
color: Colors.red,
width: animation.value,
height: animation.value,
),
);
} else {
return Center(child: CircularProgressIndicator());
}
});
}
}
Please separate your animated widget. In your code, every setState(...) call will re-request the http.get(...).
Do something like this...
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
home: const Scaffold(
body: Center(
child: Home(),
),
),
);
}
}
class Home extends StatelessWidget {
const Home();
#override
Widget build(BuildContext context) {
return FutureBuilder(
future: Future<void>.delayed(const Duration(seconds: 2), () {}),
builder: (context, snapshot) =>
snapshot.connectionState == ConnectionState.done
? const Center(child: AnimatedContainer())
: const Center(child: CircularProgressIndicator()),
);
}
}
class AnimatedContainer extends StatefulWidget {
const AnimatedContainer();
#override
_AnimatedContainer createState() => _AnimatedContainer();
}
class _AnimatedContainer extends State<AnimatedContainer>
with SingleTickerProviderStateMixin {
AnimationController _controller;
Animation<double> _animation;
#override
void initState() {
super.initState();
_controller = AnimationController(
duration: const Duration(milliseconds: 3000),
vsync: this,
);
_animation = Tween<double>(begin: 10, end: 300).animate(_controller);
_animation.addListener(() {
setState(() {});
});
// _controller.repeat();
_controller.forward();
}
#override
Widget build(BuildContext context) {
return Container(
color: Colors.red,
width: _animation.value,
height: _animation.value,
);
}
#override
void dispose() {
_controller.dispose();
super.dispose();
}
}
in this simple below ui i have Container right of screen and i want to collapse and expand it with elastic animation, for example on expand elasticIn animation and for collapse elasticOut.
Is this what you need?
import 'package:flutter/material.dart';
import 'package:flutter/physics.dart';
import 'dart:math';
void main() => runApp(new MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: "Spring Box",
theme: ThemeData(),
home: HomePage(),
);
}
}
class HomePage extends StatefulWidget {
#override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> with SingleTickerProviderStateMixin {
Animation animationIn, animationOut;
AnimationController _animationController;
#override
void initState() {
_animationController = AnimationController(
vsync: this,
value: 1.0,
duration: Duration(milliseconds: 500),
);
animationIn = CurvedAnimation(parent: _animationController, curve: Curves.elasticIn);
animationOut = CurvedAnimation(parent: _animationController, curve: Curves.elasticIn);
}
_toggleExpanded() {
if (_animationController.status == AnimationStatus.completed) {
_animationController.reverse();
} else {
_animationController.forward();
}
}
#override
Widget build(BuildContext context) {
var isExpanded = _animationController.status != AnimationStatus.completed;
return Scaffold(
floatingActionButton: FloatingActionButton(
onPressed: _toggleExpanded,
child: Icon(Icons.add),
),
body: Row(
mainAxisAlignment: MainAxisAlignment.end,
children: <Widget>[
CollapsAnimation(
animation: isExpanded ? animationOut : animationIn,
child: Container(
color: Color(0xFF404bc4),
),
),
],
),
backgroundColor: Color(0xFFe8e8e8),
);
}
}
class CollapsAnimation extends AnimatedWidget {
CollapsAnimation({key, animation, this.child})
: super(
key: key,
listenable: animation,
);
final Widget child;
final Tween tween = Tween<double>(begin: 0, end: 80);
#override
Widget build(BuildContext context) {
Animation<double> animation = listenable;
var animationValue = tween.evaluate(animation);
double width = animationValue >= 0.0 ? animationValue : 0.0;
return Container(
width: width,
child: child,
);
}
}
I have a text widget I want to rotate for 360 degrees only on Y axis.
Here is the code I currently have, it only rotates up to a certain point.
import 'package:flutter/material.dart';
class Loader extends StatefulWidget {
#override
_LoaderState createState() => _LoaderState();
}
class _LoaderState extends State<Loader> with SingleTickerProviderStateMixin {
Animation _rotate;
AnimationController _controller;
#override
void initState() {
super.initState();
_controller = new AnimationController(
vsync: this,
duration: new Duration(seconds: 1),
);
_rotate = Tween(begin: 0.0, end: 3.14 * 2).animate(_controller);
_controller.forward();
}
#override
void dispose() {
super.dispose();
_controller.dispose();
}
#override
Widget build(BuildContext context) {
return Container(
child: AnimatedBuilder(
animation: _controller,
child: Text("Flutter"),
builder: (BuildContext context, Widget _widget) {
return Transform(
transform: Matrix4.rotationY(_controller.value),
child: _widget,
);
},
),
);
}
}
Do you guys have any idea how to fix this?
Thanks!
add this
_rotate = Tween(begin: 0.0, end: 3.14 * 2).animate(_controller)
..addListener(() {
setState(() {});
});