简体   繁体   中英

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())
    }
}

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
            }
        }
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM