NEW: My new book Pro SwiftUI is out now – level up your SwiftUI skills today! >>

Moving rows in a list animation

Forums > SwiftUI

Hi guys,

I have a list of items that are sorted by status(using Core Data's SortDescriptors). I have a context menu that enables the user to change status and it works. However I'm not able to figure out how to make a pleasant animation for the movment of rows. Do you have a hint? Thank you!

Code:

            List {
                ForEach(bills, id: \.self) { bill in
                    NavigationLink(destination: DetailView(bill: bill)) {
                        HStack {
                            VStack(alignment: .leading) {
                                Text("\(bill.title ?? "Unkown title")")
                                    .font(.title)

                                if bill.fixedAmount != 0.0 {
                                    Text("$\(bill.fixedAmount, specifier: "%g")").labelsHidden()
                                }
                            }

                            Spacer()

                            VStack(alignment: .trailing) {
                                Text(bill.status ?? "Unpaid")
                                    .font(.title2)
                                    .foregroundColor(bill.status == AddView.statusTypes[0] ? Color.red : Color.green)

                                if bill.status == AddView.statusTypes[1] {
                                    Text("\(bill.paidDate ?? Date(), style: .date)").labelsHidden()
                                }
                            }
                        }
                    }
                    .contextMenu {
                        Button(action: {
                            changeStatus(bill)

                        }) {
                            Text("Mark as \(bill.status == AddView.statusTypes[0] ? "Paid" : "Unpaid")")
                        }

                        Button(action: {
                            moc.delete(bill)
                            PersistenceController.shared.save()
                        }) {
                            Text("Delete")
                            Image(systemName: "trash")
                                .foregroundColor(.red) //nothing happens
                        }
                    }
                }

GIF of sluggish animation: https://gifyu.com/image/ZZA3

1      

try using
withAnimation{ }

arround the views

1      

Hi!

Tried putting the whole list, the ForEach, the HStack in withAnimation {} but sadly no luck. Thanks for the input!

1      

Hacking with Swift is sponsored by Play

SPONSORED Play is the first native iOS design tool created for designers and engineers. You can install Play for iOS and iPad today and sign up to check out the Beta of our macOS app with SwiftUI code export. We're also hiring engineers!

Click to learn more about Play!

Sponsor Hacking with Swift and reach the world's largest Swift community!

So I found the answer in case someone will have the same situation: adding .id(UUID()) modifier to the List makes the shady animation go away but sadly you can't animate the change. It will be instantaneously.

Explanation: https://www.hackingwithswift.com/articles/210/how-to-fix-slow-list-updates-in-swiftui

1      

do you have your project hosted somewhere (e.g. github) so I can try a few things?

There's quite a few other views / structs in here required to operate so would be easier if I could save your enture project and see if I can work it out

1      

one thing which might be worth trying first is to put the withAnimation into your button


Button(action: {
withAnimation {
                            changeStatus(bill)

                       }
                       }) {
                            Text("Mark as \(bill.status == AddView.statusTypes[0] ? "Paid" : "Unpaid")")
                        }

1      

Hi Richard,

Thanks for the help, i tried wrapping up the function in a withAnimation {} but no luck. Anyways, here's the link: https://github.com/Tiberiu27/AppProjects Recently I found out that .id(UUID()) crashes the app on the first launch each month :(. Thanks again!

1      

so about 90 minutes into trying to fix your issue, I'm afraid to say that I can't fix it but I can narrow down the issue at least.

Issue is certainly related to having a context menu and a list together.

If you remove the list and just have a ForEach then the animation is not jerky anymore and it is more instananeous (like when you had the .id but hopefully without the crashes. It does make your UI look horrible but I'm sure that could be re-coded to look good again using some vStacks and proper layout to replicate what the list was doing for you.

Or, below link has a couple of options. The delay option makes the action instananeous without messing up the UI so that's worth some consideration.

My personal preference is to remove the context menu and instead have a button in the row itself.You get a really nice animation there where you see the row travel from the unpaid section to the paid section.

https://stackoverflow.com/questions/60358948/swiftui-delete-row-in-list-with-context-menu-ui-glitch

Sorry I couldn't quite get you a total fix with your current setup but I think you've got a few options here you can try out and see if any of them suit.

Or now you know the combination causing the problem then you may want to do a bit more googling and see if there are any other solutions out there.

Good luck

Richard

1      

Hi Richard,

Thank you so much for putting the time and effort, appreciate it. I'll mess around with your suggestions as soon as I get off from work (two days from now). Have a good one!

1      

no worries.

let me know what you decide in the end, I'm curious

1      

Hi Richard,

I experimented with your suggestions above and I think I'll end up ditching the context menu and adding a longPressGesture to the status section of the row. Like this: https://gifyu.com/image/ZOeX . I find it much more pleasing from an animation perspective :D

                            .onLongPressGesture {
                                withAnimation {
                                    changeStatus(bill)
                                }
                            }

Thank you again for your help. Cheers!

1      

looks good! :)

1      

Hacking with Swift is sponsored by Play

SPONSORED Play is the first native iOS design tool created for designers and engineers. You can install Play for iOS and iPad today and sign up to check out the Beta of our macOS app with SwiftUI code export. We're also hiring engineers!

Click to learn more about Play!

Sponsor Hacking with Swift and reach the world's largest Swift community!

Archived topic

This topic has been closed due to inactivity, so you can't reply. Please create a new topic if you need to.

All interactions here are governed by our code of conduct.

 
Unknown user

You are not logged in

Log in or create account
 

Link copied to your pasteboard.