Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

SwiftUI listRowBackground can't animate?

I'm trying to imitate the normal UITableView behavior of a cell hiliting when you tap it, and then fading out. I'm getting pretty close except:

  • .background() doesn't fill the entire list cell, it just fits around the content.
  • .listRowBackground() does fill the cell, but it doesn't animate.

Is there a way to animate a list row background?

Below is the source for full context. As written, because listRowBackground doesn't animate, you never see the background change at all. If you change it to background instead, it animates as expected but doesn't fill the cell.

struct Profile {
    let name: String
    var selected: Bool
    var hilited: Bool = false
}

extension Profile: Identifiable {
    var id: String { name }
}

struct ProfilesPicker: View {
    @State var profiles: [Profile]

    var body: some View {
        List {
            ForEach(0..<profiles.count) { index in
                let profile = profiles[index]

                CheckCell(name: profile.name, checked: profile.selected)
                    // using .background() gets a proper fade but doesn't fill the cell
                    .listRowBackground(Color(profile.hilited ? UIColor.systemFill : UIColor.systemBackground))
                    .onTapGesture {
                        profiles[index].hilited = true
                        withAnimation(.easeIn) {
                            profiles[index].hilited = false
                            profiles[index].selected.toggle()
                        }
                    }
            }
        }
    }
}

struct CheckCell: View {
    let name: String
    let checked: Bool

    var body: some View {
        HStack {
            Text(name)
            Spacer()
            if checked {
                Image(systemName: "checkmark")
            }
        }
        .contentShape(Rectangle())
    }
}
like image 290
Uncommon Avatar asked Apr 07 '26 08:04

Uncommon


1 Answers

Use delay and add animation to listRowBackground.

struct ProfilesPicker: View {
    @State var profiles: [Profile]
    
    var body: some View {
        List {
            ForEach(0..<profiles.count) { index in
                let profile = profiles[index]
                
                CheckCell(name: profile.name, checked: profile.selected)
                    .onTapGesture {
                        profiles[index].hilited = true
                        
                        DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) { //<==Here
                            profiles[index].hilited = false
                            profiles[index].selected.toggle()
                        }
                    }
                    .animation(.default)
                    .listRowBackground(Color(profile.hilited ? UIColor.systemFill : UIColor.systemBackground).animation(.easeInOut)) //<==Here
            }
        }
    }
}
like image 173
Raja Kishan Avatar answered Apr 08 '26 22:04

Raja Kishan



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!