I'm trying to customize a showGeneralDialog to show my Transform.scale animation. I'm just wondering if there is a way to change the default animation of the widget to a curved animation?
like a1 and a2 within:
transitionBuilder: (context, a1, a2, widget) {
For example, I would like the Transform.scale to have a bounceIn effect.
Also, could someone please explain the difference between transitionBuilder: (context, a1, a2, widget) {} and pageBuilder: (context, animation1, animation2) {} for the showGeneralDialog widget? And how do I properly use them?
Thanks!
Yes it is possible by override transitionBuilder parameter.
1. Creating New showDialog() method
Commonly, developer uses showDialog to put some dialog that overlays underlying
screen.
In this app, it is convenient to have new method so it can be simply reused
through out our application.
new_dialog.dart
Future<T> showNewDialog<T>(
return showGeneralDialog(
...
transitionDuration: const Duration(milliseconds: 400),
transitionBuilder: _buildNewTransition,
);
}
We only reuse showGeneralDialog() method, and customized its animation-related
parameters : its transitionDuration for Duration and its transitionBuilder
as Animating component.
2. Defining new Animating component
In this demo we create simple animation by wrapping our child widget into
ScaleTransition. Then we defined its curve, rather in curve param only, or
in both of curve and reverseCurve.
new_dialog.dart
Widget _buildNewTransition(
BuildContext context,
Animation<double> animation,
Animation<double> secondaryAnimation,
Widget child,
) {
return ScaleTransition(
scale: CurvedAnimation(
parent: animation,
curve: Curves.bounceIn,
reverseCurve: Curves.bounceIn,
),
child: child,
);
}
3. Display our new Dialog
Lastly, we can call this animated dialog anywhere in our app by using this
code :
main.dart
RaisedButton.icon(
icon: Icon(Icons.info_outline),
label: Text("Open Dialog"),
onPressed: () {
showNewDialog(
context: context,
builder: (BuildContext context) {
return AlertDialog(
title: Text("Bounce In"),
);
},
);
},
),
Repository
you may look repository here. Github
Demo
pageBuilder vs Transition builder
If we take look into DialogRoute definition in Flutter Repo, we can conclude that
each showDialog() method will runs and passing parameters in this sequences :
showDialog
showGeneralDialog
_DialogRoute
PopupRoute
ModalRoute
and so on
...
Take look at buildTransitions method _DialogRoute which return FadeTransition by default.
As I tried, if we put transitionBuilder : null, by calling showGeneralDialog, The App will displays Dialog and still got animated.
return showGeneralDialog(
...,
transitionBuilder: null,
);
Conversely, if we put pageBuilder : null, by calling showGeneralDialog, The App will displays nothing.
return showGeneralDialog(
...,
pageBuilder: null,
transitionBuilder: _buildNewTransition,
);
We may conclude that :
pageBuilder although has some parameters of Animation and
SecondaryAnimation, it is meant for defining Widget to display.
transitionBuilder it is meant for defining animation to be
processed, as Flutter displaying the Dialog
Related
I am using IconButtons in my application for opening popups, deleting ListTiles from ListViews, navigating to other views etc.
To my surprise the onPressed callback always gets triggered before the animation starts to play resulting in that the animation will not play at all. This is confusing to the user because there is no feedback that he pushed the button.
The setup looks something like this.
This is the code for the add button in the top right corner:
IconButton(
onPressed: () {
showDialog(
context: context,
builder: (context) {
return AddDevicePopup(
...
).build(context);
});
},
icon: const Icon(
Icons.add_circle_outline_rounded,
size: 30.0,
)
)
When the user taps the button the popup immediately appears but the animation won't get played.
This is the same for the IconButtons on the tiles:
the edit button opens a popup immediately and the ripple or splash animation won't play.
the delete button removes the element from the list. In this case the ListTile element gets removed and so the IconButton disappears without the animation getting played.
In every case there is a Material widget that is an ancestor of the IconButton so wrapping it in a Material widget does not solve the problem. I have double checked it by removing the showDialog part from the callback, in these cases all of the IconButtons play the splash / ripple animation as expected.
How do I make the onPressed to wait for the animation to at least be started. I did not find any solution. Is is possible to trigger this animation via code? In that case I can add that to the beginning of the onPressed callback.
To add animations, you must use showGeneralDialog instead of showDialog.
The implementation looks like this:
showGeneralDialog(
barrierDismissible: true,
barrierColor: Colors.black.withOpacity(0.5),
transitionDuration: const Duration(milliseconds: 200),
context: context,
pageBuilder: (_, __, ___) {
return AddDevicePopup(
...
).build(context);
},
//Customize your animation here
transitionBuilder: (_, a1, __, child) {
return Transform.scale(
scale: a1.value,
child: Opacity(
opacity: a1.value,
child: child,
),
);
},
);
I'm developing a gallery app looking like whatsapps photo gallery. I want the appbar title change when my carousel slider changes. I tried it with setstate but because I show the carouselslider in a showdialog, it doesn't work and I think it can be cause performance issues. I use getx in the project and is there any way to do it without setstate?
Here is my AppBar widget
showGeneralDialog(
context: context,
barrierDismissible: true,
barrierLabel: MaterialLocalizations.of(context)
.modalBarrierDismissLabel,
barrierColor: Colors.black45,
transitionDuration:
const Duration(milliseconds: 200),
pageBuilder: (BuildContext buildContext,
Animation animation,
Animation secondaryAnimation) {
return Dismissible(
direction: DismissDirection.vertical,
key: const Key('key'),
onDismissed: (_) => Navigator.of(context).pop(),
child: Scaffold(
appBar: AppBar(title: Text(photoSender)),
And body of the scaffold is a carouselsliderbuilder, so when the carousel changes, I want the photoSender variable to change.
Any ways to do this?
Declare you photoSender variable as Rx<String>:
final photoSender = Rx<String>("");
Wrap your Text widget with Obx/GetX:
appBar: AppBar(title: Obx(()=>Text(photoSender.value))),
Whenever your photoSender variable`s value changes, it will automatically update the text in your app bar.
To update the value:
photoSender.value = "John";
Flutter. There are two screens. On the first screen, there is one widget in the center (a container with text). On the second screen (ListView), the same (container with text), but shifted to the side, and another one is added(TextField). How do I animate the transition between these screens? Move the first widget (container) I know how. But how do I add a TextField at the same time ? ......as an option, I thought to apply the opacity of the TextField , but this place on the first screen is already occupied. Probably a complete replacement of the screens is needed here.
Here you have example of quick animation. This code should be in onpressed
Navigator.push(
context,
PageRouteBuilder(
transitionsBuilder: (BuildContext context,
Animation<double> animation,
Animation<double> secAnimation,
Widget child) {
animation = CurvedAnimation(
parent: animation,
curve: Curves.fastLinearToSlowEaseIn);
return ScaleTransition(
scale: animation,
child: child,
alignment: Alignment.center,
);
},
transitionDuration:
const Duration(milliseconds: 300),
pageBuilder: (BuildContext context,
Animation<double> animation,
Animation<double> secAnimation) {
return **urpage**();
}));
I am trying to Use to OpenContainer() Widget in my app and my app requires varying animation speeds for both closing and opening the OpenContainer() widget is it possible to change it dynamically or specify it
OpenContainer Widget have a transitionDuration property that can be set to desired duration for animation.
OpenContainer(
transitionDuration: Duration(milliseconds: 500),
transitionType: ContainerTransitionType.fadeThrough,
closedShape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(50.0),
),
closedBuilder: (context, action) => CloseWidget(),
openBuilder: (context, action) => OpenWidget(),
);
You can do further reading here.
Hope this helps!
I am trying to implement shared_axis_transition on my flutter application's bottom navigation. The setup consists of A root page with bottom navigation bar and 4 other pages which changes according to the index of bottom navigation. The problem is, each of the widgets are stateful and have their own initstate. When I try to apply animation, after animation completes, the widget rebuilds itself and sort of flickering effect is seen. How do I solve the issue? My code pattern is as follow:
RootWidget{
body: PageTransitionSwitcher(
duration: const Duration(milliseconds: 300),
transitionBuilder: (
Widget child,
Animation<double> animation,
Animation<double> secondaryAnimation,
) {
return SharedAxisTransition(
child: child,
animation: animation,
secondaryAnimation: secondaryAnimation,
transitionType: _transitionType,
);
},
child: [First(),Second(),Third(),Fourth()].elementAt[index],
),
),
bottomNavigationBar(),
}
Each of the widget have their own initstate which I believe is causing this.
p.s For the first time since I started flutter, animations in debug environment looks smoother than animation in release...