I want to make a custom transition like PageView in flutter when navigate to another page like image below but I do not know how. I used SlideTransitiondid but it does not give me the desired result
import 'package:flutter/material.dart';
import 'package:get/get.dart';
class SlideTransitions extends CustomTransition {
#override
Widget buildTransition(
BuildContext context,
Curve curve,
Alignment alignment,
Animation<double> animation,
Animation<double> secondaryAnimation,
Widget child) {
return Align(
alignment: Alignment.center,
child: SlideTransition(
position: Tween(begin: Offset(1.0, 0.0), end: Offset(0.0, 0.0))
.animate(animation),
child: child,
),
);
}
}
pageview transition image
you can use page_transition PageTransitionType.rightToLeft . It's kinda similar to pageview swipe
Related
I need to animate current screen A out, then screen B in. PageRouteBuilder, transition:
#override
Widget buildTransitions(
BuildContext context,
Animation<double> animation,
Animation<double> secondaryAnimation,
Widget child,
) {
var animCurrentWidget = Tween<Offset>(begin: const Offset(0, 0), end: const Offset(0, 1))
.chain(CurveTween(curve: const Interval(0, 0.5, curve: Curves.linear)))
.animate(animation);
var animNewWidget = Tween<Offset>(begin: const Offset(0, 1), end: const Offset(0, 0))
.chain(CurveTween(curve: const Interval(0.5, 1, curve: Curves.linear)))
.animate(animation);
return Stack(
children: <Widget>[
SlideTransition(position: animCurrentWidget, child: parent, transformHitTests: false),
SlideTransition(position: animNewWidget, child: child),
],
);
}
Pretty simple, current screen leaves with up->down, new one goes in with sliding down->up after first one left.
But the tricky part is that you need to have access to current Widget on screen to do that, which removes use of
onGenerateRoute: MyCustomRouting.generateRoute
And forces me to work with routes in local scope of every possible screen app can have.
What are the best practices for tasks like that?
Is there a way to get current widget inside MyCustomRouting.generateRoute without going full static?
Is there a way to get current 'on top' widget inside other widget in the tree?
I am using Hero in my app for smooth transitions but I faced an issue: I would like the Hero-Widget rotate 90 degress on transition. I found out I can use flightShuttleBuilder for this and tried it like this:
flightShuttleBuilder: (
BuildContext flightContext,
Animation<double> animation,
HeroFlightDirection flightDirection,
BuildContext fromHeroContext,
BuildContext toHeroContext,
) {
final Widget toHero = toHeroContext.widget;
return RotationTransition(
turns: animation,
child: toHero,
);
},
As you can see I used the RotationTransition and it kind of works but not exactly how I want it. It rotates the widget during the flight by 360 instead of 90.
The widget should stay rotated on the 2nd screen. I tried that with RotatedBox. This is the full widget on the 2nd screen:
child: Hero(
tag: 'america',
flightShuttleBuilder: (
BuildContext flightContext,
Animation<double> animation,
HeroFlightDirection flightDirection,
BuildContext fromHeroContext,
BuildContext toHeroContext,
) {
final Widget toHero = toHeroContext.widget;
return RotationTransition(
turns: animation.drive(Tween(begin: 0, end: 0.25)),
child: toHero,
);
},
child: RotatedBox(
quarterTurns: 1,
child: SizedBox(
height: 100,
width: 100,
child: SvgPicture.asset(
'assets/icons/america.svg',
),
),
),
),
Is there a way to get this done and how would I do that? Couldn't find anything on this. Let me know if you need any more info!
With the help of #Michael Horn I got it working. As he suggested I changed the turns value. That fixed the rotation. However I wanted the widget to stay rotated on the 2nd screen. I did that with RotatedBox. But when simply giving it the value 1, Hero will take that Rotated Widget for flightShuttleBuilder and the sets it back when building is finished. I fixed this by changing the quarterTurns after all the widgets are build:
int rotation = 0;
#override
void initState() {
super.initState();
WidgetsBinding.instance!.addPostFrameCallback((timeStamp) {
setState(() {
rotation = 1;
});
});
}
and my widget:
child: Hero(
tag: 'america',
flightShuttleBuilder: (
BuildContext flightContext,
Animation<double> animation,
HeroFlightDirection flightDirection,
BuildContext fromHeroContext,
BuildContext toHeroContext,
) {
final Widget toHero = toHeroContext.widget;
return RotationTransition(
turns: animation.drive(Tween(begin: 0, end: 0.25)), // <- for the during-flight 90 degree rotation
child: toHero,
);
},
child: RotatedBox(
quarterTurns: rotation, // <- important to not change that dynamically
child: SizedBox(
height: 100,
width: 100,
child: SvgPicture.asset(
'assets/icons/america.svg',
),
),
),
),
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 design a music playlist page. So far I am able to create a listview with song cards. When I click on any song, a custom bottom bar appears and the audio starts playing. However, I just hold a state with boolean and show the bottom bar according to that. Instead, I want it to appear like sliding up and reach to the position. Let say in 0.5 seconds.
I have a custom NavBar class
class NavBar extends StatefulWidget
And I use this class in build similar to:
return Column(
children: [
SizedBox(
height: constraints.maxHeight * 0.5,
hild: SlidingBanners(),
),
Expanded(
child: Lists(),
),
NavBar()
],
);
How can I such animation?
Use a SizeTransition widget https://api.flutter.dev/flutter/widgets/SizeTransition-class.html
"SizeTransition acts as a ClipRect that animates either its width or
its height, depending upon the value of axis. The alignment of the
child along the axis is specified by the axisAlignment."
Widget build(BuildContext context) {
return SizeTransition(
sizeFactor: CurvedAnimation(
curve: Curves.fastOutSlowIn,
parent: _animationController,
),
child: Container(height: 100, color: Colors.blue)
);
}
init animation controller in stateful widgets initState()
#override
void initState() {
super.initState();
_animationController = AnimationController(
vsync: this, duration: const Duration(milliseconds: 500));
}
Make sure your stateful widget uses SingleTickerProviderStateMixin
class _NavBarState extends State<NavBar>
with SingleTickerProviderStateMixin {
late AnimationController _animationController;
then open and close with
_animationController.forward()
_animationController.reverse()
You can pass the _animationController into the NavBar widget's constructor from its parent if you want the parent to control the animation.
Alternatively you can use an AnimatedContainer widget and setState with its height 0 or 100 depending on if Nav should be shown. This becomes a problem for some widgets that cannot be squished to height of 0 though and I would not recommend for any container that contains anything but text
One solution would be to use a SnackBar widget. Since it's automatically animated, you wouldn't want to worry about manually animating the bottom bar. You can insert your Audio Player (bottom bar) widget to the child of the SizedBox.
The bottom bar is made visible by,
ScaffoldMessenger.of(context).showSnackBar(snackBar);
This bottom bar is dismissed (hidden) by dragging down or by,
ScaffoldMessenger.of(context).hideCurrentSnackBar();
There maybe many other solutions as well to this, but reading your question, I hope this is what you wanted.
return Center(
child: ElevatedButton(
onPressed: () {
final snackBar = SnackBar(
duration: Duration(days: 365),
content: SizedBox(
height: 100,
//insert your audio player widget here
child: Column(
children: [
Text("YOUR AUDIOPLAYER WIDGET HERE"),
Text("Audio Controls Here"),
ElevatedButton(
onPressed: () {
ScaffoldMessenger.of(context).hideCurrentSnackBar();
},
child: Text("Audio Player Minimize"),
),
],
),
),
);
ScaffoldMessenger.of(context).showSnackBar(snackBar);
},
child: Text('Open Audio Player'),
),
);
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...