skip to Main Content

While testing out SwiftUI, I’ve found that AsyncImage does not work well while animating a transition. It seems to settle on its final position of the transition before the rest of the UI has moved there, making the animation seem weird or off.

My main question is: is there any way to access the SwiftUI animation of the AsyncImage and make it work with other animations elsewhere in the app?

The weird part is that, if I change it to some other view (that doesn’t have animations), the transition behaves correctly, so I believe that the root of the problem is something to do with AsyncImage’s default animation for changing between its phases (loading, failed or loaded).

The overlay that is presented is described as such:

    if isBottomSheetVisible {
                VStack(alignment: .leading) {
                    AccountSelectorHeader()
                    ForEach(accounts) { account in
                        AccountRow(
                            account: account,
                            isLast: accounts.last == account
                        )
                    }
                }
                .padding(.bottom, 24)
                .background(Color(.tableViewHeaderBackgroundColor)
                                .cornerRadius(24, corners: [.topLeft, .topRight])
                                .edgesIgnoringSafeArea(.bottom)
                )
                .transition(
                    .move(edge: .bottom)
                )
            }

And each image is only a standard AsyncImage inside the AccountRow view:

    AsyncImage(url: URL(string: account.image)) {
            $0
                .resizable()
                .clipShape(Circle())
        } placeholder: {
            ProgressView()
        }

2

Answers


  1. I faced a similar issue and it worked fairly well if you use the init(url:scale:transaction:content:).

    With the code below I got the image move in with the sheet and on disappear it didn’t move but was removed as the sheet obscured it:

    AsyncImage(
                url: URL(string: url),
                transaction: Transaction(animation: .default)
            ) { phase in
                switch phase {
                case .success(let image):
                    image
                        .resizable()
                default:
                    Image("defaultImage")
                        .resizable()
                }
            }
    
    Login or Signup to reply.
  2. That’s indeed weird, just tried with an own implementation of asyncImage and it has a similar behaviour, perhaps it is easier for you to fix it from there: Simple iOS13 AsyncImage. I will take a look to it too if I have time.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search