Flutter: Creating a scroll view that contracts center item before allowing the list to scroll - flutter

I'm creating a scroll view that pads that center item with some extra space vertically. I want to accomplish two things:
1- Shrink the center item's padding at the same rate the user is moving his finger. For example, if the padding of the center item is 50 pixels and the user moved his finger for 10 pixels then I would like to decrement the padding to 40.
2- I would like to stop the list view from actually scrolling until the padding for the center item is 0. The list view should scroll as normal once the center item's padding is 0.
I'm a little lost here. I've been trying playing around with implementing my own ScrollController and ScrollPhysics but I haven't been able to achieve exactly what I'm looking for. I also saw that there was a class in Flutter called ScrollPosition that controls the position for each scrolling widget but I haven't been able to figure out how to use these to accomplish the behavior I'm looking for.
Could someone point me in the right direction?

Change the physics property of the ListView, NeverScrollablePhysics() doesn't allow scrolling.
Maybe use a GestureDetector for detecting the swipes.
Be careful of the placement of this widget though.
It can interfere with the normal scrolling of the listView.
Try experimenting with the animationController instead of calling setState() multiple times,
it's wasteful to refresh the screen multiple times just to change the padding.

Related

Hero animation on same widget -> rebuild does not follow

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

Reusing the same instance of a widget in a ListView

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?

Flutter Hero-like transition in PageView

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.

How to get a widget to move across the screen every X seconds?

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.

UIScrollView Vertical Pan Snapping to top or bottom of view

I have an image that is 320x480 and upon orientation change this image obviously hangs out of view. There are some images where the focal point of it sits with it's bottom cut off (which isn't undesirable). My issue however is when the user pans vertically to see the full image, the view appears to snap to the bottom meaning the top of the focal point is cutoff. What I wish to happen is that the users can "free-scroll" through the image and perhaps move the images so the focal point is centre screen, instead of cutting off the top and bottom. I understand this is a difficult concept to describe in words so I've attached some images below.
This is how it starts:
This is where it snaps to the bottom:
This is the kind of view I wish to have but cannot:
Is there a way to control this "snapping" or perhaps a method I could use to override it when dealing specifically with this kind of orientation? My issue is that i WANT it to snap when panning left/right onto the other images in the ScrollView, just not up/down.
EDIT:
pagingEnabled is the property that controls this snapping, but is there anyway to detect if the movement is Up/Down or Left/Right and disable or enable this property in each occasion?
Cheers for any help you can offer
You can try using two nested scroll views; one is limited to scrolling horizontally with paging enabled, and one (or one for each page if you're displaying several images?) limited to scrolling vertically with paging disabled. By default this will work like you said, paging/snapping horizontally but free scroll vertically. However, it will only let you scroll in one direction at a time (either horizontally or vertically, not diagonally).
If you want to use nested scroll views like this but you'd like to allow scrolling/dragging in both directions simultaneously, take a look at my solution for this: Nested UIScrollViews scrolling simultaneously