Я пытаюсь сымитировать нормальное поведение 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())
    }
}
1
Uncommon 26 Фев 2021 в 21:40

1 ответ

Лучший ответ

Используйте задержку и добавьте анимацию в 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
            }
        }
    }
}
0
Raja Kishan 26 Фев 2021 в 19:17