SwiftUI listRowBackground 无法设置动画?

Unc*_*mon 7 ios swift swiftui swiftui-list

我试图模仿单元格的正常 UITableView 行为,当您点击单元格时,它会启动,然后淡出。我已经非常接近了,除了:

  • .background()不会填充整个列表单元格,它只是适合内容。
  • .listRowBackground()确实填充了单元格,但它没有动画。

有没有办法为列表行背景设置动画?

以下是完整上下文的来源。正如所写,因为listRowBackground没有动画,所以你根本看不到背景变化。如果您将其更改为background,它会按预期进行动画处理,但不会填充单元格。

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())
    }
}
Run Code Online (Sandbox Code Playgroud)

Raj*_*han 6

使用延迟并向 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
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)