I have a FlameGame widget and have 2 overlays.
Overlay A (with animation)
Overlay B (with button)
At some point in code I need to display booth overlays.
Overlay A will disappear after animation ends.
Overlay B will disappear after button press.
My problem is that if I press the button on overlay B before the animation ends on overlay A, it causes a rebuild on overlay A and the animation restarts. (it does not look nice...)
Tried switching around the order in witch overlays are added. Only makes A appear behind B.
Tried making A stateful. Still, the removal of B causes A to call initState() again.
Until someone suggest a non hacky way, I solved it by:
Adding a double? variable to the FlameGame component of which I am added the overlays to and in the initState() of the A overlay I check if the value is non null.
If it is I set it and keep setting it every time in the addListener() of the animation.
If it is non null, I set my animation value to that value.
In the dispose() I set the double? to null.
It is messy, but if anyone will need solution to this exact problem, I will try to provide the code.
Related
When I try to use the Hero animation to transition between two times the same widget, but one is limited through his parents on its size, the animation does scale down on return even though it should scale up. It always scales to the last recorded size when the second screen was pushed. Whether this is because the Hero Animation saves the source heros size or, the initial screen does render earliest when the hero is at its origin place and size, I don't know.
Thus my question if you know a way to fix this behavior, or if this might be an unexpected behavior of the Hero widget and I should post a flutter issue.
Setup:
ValueNotifier is used to listen to changes and rebuilds both widgets (as they are literally the same)
plus button adds element to valueNotifier and calls notifyListeners
minus button removes last element element to valueNotifier and calls notifyListeners
Steps to reproduce:
start dartpad.dev
click arrow right fab
add as many entries with the plus button, so the widget with the white background is higher than before
click the arrow left button in the top left corner
watch the animation resize, even though the widgets should be rebuild at the same time
At first — I have a widget, it contains and plays a specific animation which state cannot be saved or interrupted because animation data comes from a web server permanently and this stream is important.
Second — I have a ListView.builder with 'infinite' list of Cards (simple cards, doesn't important in this situation, app's screen contains 5 of them at the same time).
The problem is: is it possible to set given animated widget on every 10-th position of the ListView using the same instance of it in order to save it's animation state and not recreate animated widget every time? It must be the same widget, the animation must continue — one widget's instance on the screen at the time.
I tried to use a Stack with the animated widget wrapped with Offstage widget on the upper layer and the ListView with 'gaps' on every 10-th position. So Animated widget lives permanently and when it goes out of the screen I 'turn it off' with Offstage. And when it should appear on scroll I 'switch it on' with Offstage. But it is very difficult to position animated widget and synchronize its position with a scroll position of the ListView. For this purpose I use a GlobalKey for every 'gap' in the ListView, define it's Render Rectangle to position my Animated widget on/in the given gap.
Any ideas to solve this task more elegant? Maybe it is possible to make some 'deep copy' or 'singleton' or keep it alive (somehow) in the ListView or use some slivers, and reuse the same instance of it again and again when it appears?
I have an image in one page of the PageView. I want to animate this image to the next page when i go to it, sort of like when you use Hero animations in navigator page transitions. Any ideas how this can be achieved?
In order to achieve an animation similar to the hero animation. Basically what we will implement is this, you will need 5 elements:
The initial global coordinates
The final coordinates
Initial widget size
Final widget size
The widget you want to animate
Now in order to create this animation that spans the 2 screens we will need to use the overlay that is present in flutter. link
Add to the Overlay the widget that is to be animated (Not the widget present on the screen, a new instance).
Position this overlay entry to be in the starting coordinate of the animation (The original widget's position).
Hide the original widget.
Create an animation that changes the x and y coordinates to the create the custom motion, this can be any curve, the simplest being a simple tween between the starting coordinate and the end coordinate.
Another animation that animates size change between the start and end size. This animation can be combined with the previous one. (One tween animation but the values are calculated manually)
After the animation is done, remove the overlay entry, and show the new widget. (This can be done as a timed operation or as a call back operation)
This is the most flexible between all of the available options since you have access to the widget in all of its states. However you must be very careful when using this method as it might cause a slowdown if not properly implemented.
This packages does what you want https://pub.dev/packages/coast
It is essentially taking the same approach as Flutter’s Hero and HeroController: Detect when a transition is started, search through the element trees of the source and target pages for the widgets marked for animation (heroes, crabs), pair them up based on their tags, and finally create an entry in an Overlay whose position and size is the interpolation between those on the source and target pages.
When you swipe vertically, image is dragged towards the swipe, with fading out animation of black background.
And after release, it smoothly returns to it's previous position on the screen, like Hero animation does.
How is it possible to recreate such an effect using Flutter? The same scenario, in fullscreen photo view.
photo_view package is desired for fullscreen, so it shouldn't interfere with zooming.
What you need is actually an out-of-the-box widget, and it's surprisingly easy to use. It's called Hero. Basically, you wrap the widget you want to animate like that in a Hero widget, with a specific tag string, and, when you navigate to another screen, you wrap the destination widget in another Hero with the same tag. An effect like the one you shared can be achieved by wrapping two widgets with the same photo with Heroes in different PageRoutes.
Check out this Flutter widget of the week video to get you started, and this Flutter.dev article for a more detailed explanation on Hero widgets.
Edit: I see you are looking for a more specific image-viewer behavior. Then, I suggest you use the photo_view package, which includes many functionalities to visualize images, including the hero transition with swipe-dow-to-dismiss behaviors, pinching to zoom, etc.
I found the solution.
To create such an animation, you should use extended_image package, which has SlideOutPage widget for creation of such transitions.
Basically I'm trying to build a game to learn flutter more.
Right now I'm just trying to get a Text widget to move from the top of the phone screen, towards the bottom of the phone screen... I'm building a Space Invaders type of game with just Text.
From what I've read by googling the problem, should I use Flame? Or can everything be done by just using the base Flutter framework (collision detection, moving widgets, etc...)? Thanks.
You can use Draggable class for dragging the item.
A simple way to solve this problem is to have the moving Text widget a child of the Stack() widget. Actually, the child of the Stack() widget is a Positioned() widget, which has left and top properties, which you can update periodically with a Timer.periodic function to move the widget down by incrementing top property. So, your Text widget is a child of the Positioned() widget, that you use for, well, positioning.
I have a working example of this in my slowly_moving_widgets_field project, where I have a bunch of arbitrary widgets moving about the screen every X seconds as you desire.