Hero animation after deleting element from list - how to stop it trying to animate a blank box? - flutter

Basic setup:
I have a ListView builder that generates a list based on a List.
Each element of the list is wrapped with a Hero() widget and had a unique tag.
List renders just fine, GestureDetector initiates a 'Details' page on tap, with same widget wrapped in Hero() widget with same tag, and animates just fine, as does the 'return' animation on Navigator.pop();
The problem is...
I allow the user to delete the list element on the details page, if they do this, when I close the page with .pop(), the Hero animation basically animates a blank box of the original size back over the top of the newly rendered (and shorter list) making it look like there are 'blanks' in the list.
I originally thought it was an issue with the state of the list and the list not updating, but lots of checking proves the list is being updated, and the widgets are being re-rendered exactly as they should, it's just that there's a blank box sitting on top of them because of the Hero animation caused by the deletion.
Remove the Hero() widget wrapper and it works fine.
Break the 'tag' so it no longer matches between the two pages and it's fine (but obviously doesn't animate when navigating to the Details page).
Obviously I can stop deletion and move to the main page to avoid the animation at all or remove the animation, but is there a 'correct' way yo do this?
Anyone else hitting the same?

What a quite interesting case you got there. Is your details page statefull? One thing i imagine you could do is to setState after the deletion, so in the rebuild the deleted hero widget wouldn't exists anymore, and when poping navigation the hero navigation won't be fired because it doesn't exist anymore.

What if instead of deleting the item from the list on the pop-up up page, when the user clicks delete on the pop-up page you send a flag/parameter back to the parent page to delete the record. That way the animation will play fine as the pop-up closes, and then you can animate out the deleted record.

Related

Flutter: PageView seems to ignore PageController's page property after setState

I'm having the following problem: My library easy_image_viewer has a request to add swipe-to-dismiss. I implemented it using the Dismissible widget. However, when the user zooms in on an image, I noticed I had to find a way to "deactivate" the Dismissible widget because otherwise the user can't pan around on the zoomed-in image. I solved that by using setState and a dismissDirection variable on the state that can be either none or down.
Now for the weird part: Whenever I call setState and the dismissDirection changes, the PageView jumps back to the first item. I've tried using AutomaticKeepAliveClientMixin, but to no avail.
The code can be found here: https://github.com/thesmythgroup/easy_image_viewer/tree/pagecontroller_problem_demo
Simply run the app (example/lib/main.dart), tap on Show Multiple Images (Simple), swipe to the second image and use pinch & zoom to zoom in. You'll notice it jumps back to the first image. What am I doing wrong?
Instead of changing the dismiss direction you can use confirmDismiss i opened a PR for you to check here

Flutter SetState is not refreshing UI

I'm building multiple form pages in one class, I create 4 widgets each widgets is represent a page with text fields or cards or radio buttons.
and I create a method to switch between pages when. I press next.
This works as expected ^^
My issue UI inside first page is not refreshed unless I press ctrl + S,,
inside the first page of the form, I have created custom radio buttons they're simply cards.
and when tap on any card, there's set state method, to highlight the selected card by changing its style..
This works perfectly! at the beginning when I call the first page 1 directly as a child inside the scaffold..
However, after I created the method to switch between pages.. The UI in page 1 does not refresh..
I will put a picture..
Picture of the method to switch pages
Picture of pages widgets
picture of scaffold and how I call the widget pages
this is a picture of custom radio button which has cards, the card color change if it's selected
I tried many ways! but it didn't work..
Is what I'm trying to do correct? I'm a beginner in flutter
& I have a project to submit :(
I couldn't find a solution in google,,
Try making the widgets StatefulWidget and call setState((){}) inside the widget when you tap on the cards.
So here's what I did ^^
because the issue was just in page 1, so I in the scaffold I added page 1 as it's child directly without Switch page method..
Then inside page1, a button that will navigate to another class,
the second class has exactly the same scaffold and app bar as previous page.. But, in it's child I added calledWidget which switch between pages from 2 to 4 in my case ^^
So short words, I put page 1 in a separate page and the rest of the pages in a switch method in separate class
it works, but I hope I don't find any difficulties When saving values & integrating API to post the values
what you think?

Preserving the State of a Drawer in Flutter

I have a stateful Scaffold widget, where the body contains a list of entities with various properties (e.g. shoes or cars) and Drawer widget, which is empty at first, except for two buttons at the bottom ("Cancel" and "Filter") and a FAB. The user can add various filters with the FAB (e.g. the user can add a shoesize-filter, or a color-filter).
The problem I have is the following: Let's say the user selects various filters and works with them (i.e. ticks checkboxes, enters a shoesize, changes sliders, etc.). When the user is ready to apply the filters, he can click the "Filter" button, which closes the Drawer (onTap -> callback -> Navigator.of(context).pop()). But when the user wants to go back, reopen the Drawer, and adjust one of the filters, it obviously doesn't work, since the widget is being rebuilt from scratch.
Currently, the way the filtering works is, once the "Filter" Button is pressed, all the various values from the added filters are collected into an object FilterPackage, which is then passed via callback to the Scaffold widget, which then applies the values from the FilterPackage to the list of entities.
One solution I came up with, would be feeding this FilterPackage object to the Drawer widget in its constructor, which would provide all the information necessary to rebuild the widget just how it has to be.
Is that a reasonable solution? I have already made some research, but struggled finding a solution on what would clearly be the best and recommended way to preserve the drawer's state. Using PageStorage / PageStorageBucket seems overly complicated for this case. Or am I wrong?
Thanks in advance for any guidance.

Scrolling resets widgets flutter

I have an app with a bunch of text views inside a form. When the form scrolls, I lose the text entered in the above text fields. I would like to preserve those values. I tried adding a controller and assigning the value to a variable inside the state class but it does not work.
P.S not just widgets, but almost every type of input for example drop down buttons, radio buttons and what not.
I had a bunch of small forms inside a list view. Turns out, scrolling far enough, destroys the forms not visible to the user destroying their state. I need to lift their state up to the parent widget. For more information on how to do that, check how to keep the state of my widgets after scrolling?

How to Build All elements of sliverlist once?

I'm making a screen with comments section that has comments & their sub comments.
I use ScopedModel for managing state of the screen.
The data for comments is in a List<-model->
and for subcomments are inside the model->List<-model->.
this data is in ScopedModel.
I build a sliverList with SliverChildBuilderDelegate so it builds only widgets that are on screen.
Every comment (current_comment) has a reply button, that, after typing, adds a comment model at the end of (current_comment)model-> List<-model->
and calls notifyListener() on the ScopedModel
Now the newly added subcomment has a tag that identifies it as a new comment.
What I want:
I want that the screen scrolls to the newly added subcomment.
What I tried:
Since the newly added subcomment can be identified by a tag, I add a GlobalKey to that comment widget when its built. and then after build is complete, I scroll to that position using the offset obtained from GlobalKey added to it.
My Problem :
Since the SliverList builds elements which are visible to screen only, the newly added comment is far below the parent comment (because reply comment button is on the parent comment only) and isn't built yet. so the builder hasn't attached the GlobalKey to it yet.
Now, how do I auto-scroll to it?
Since key isn't attached to it yet, how do I locate its position & scroll to it?
Suggest me a way to either build all elements of the Sliverlist at once so the key may be attached to the element or another strategy so to auto-scroll to the newly added comment.
First solution is to set shrinkWrap property as true to the listview so it renders all children at once, and hence GlobalKey is assigned to it.
Second solution is to use a column instead, which will lead to rendering all children at once.
Both solutions are not suitable when there are too many children.