Swift UI 列表动画,用于扩展具有动态高度的单元格

san*_*.gs 7 animation swiftui

我试图在用户点击单元格时为 swiftUI 列表中的单元格展开动画。然而动画有缺陷。

我遇到了这个答案(/sf/answers/4261171841/)来帮助制作动画,但是它需要已经知道单元格展开后的预期高度。就我而言,这取决于以下数据note.text

List{
    ForEach(notes){ note in
        VStack{
            HStack{
                Text(note.title)
                    .fontWeight(.bold)
                    .foregroundColor(.gray)
                Spacer()
                Image(systemName: "chevron.right.circle")
                    .resizable()
                    .aspectRatio(contentMode: .fit)
                    .foregroundColor(.gray)
                    .frame(width: 20, height: 20)
            }
            .padding(.vertical)
            .contentShape(Rectangle())
            .onTapGesture{
                selectedNote = note
            }
            if isSelected(note) {
                Text(note.text)
            }
        }
        .padding([.bottom, .leading, .trailing], 20)
        .background(
            RoundedRectangle(cornerRadius: 25, style: .continuous)
                .foregroundColor(isSelected(noteSection) ? .red : .clear)
        )
        .animation(.default)
    }
    .onMove(perform: move)
}
Run Code Online (Sandbox Code Playgroud)

正如您从上面的代码中看到的,我需要使用一个列表,以便我可以使用 .onMove 功能。

有没有办法在链接的答案中获得相同的平滑列表动画,但对于动态扩展尺寸?

谢谢。

jca*_*uso 4

我为此苦苦挣扎了一段时间,并访问了 Stack Overflow 上的一堆现有解决方案,但它们看起来都太复杂了,尤其是现在已经是 2023 年了。

我最终偶然发现,与其将内容放入 a 中,List不如将其放入ScrollView. 然后你会得到漂亮、干净的动画,没有任何奇怪的自定义高度修改器或必须事先知道容器的高度。您只需要添加一些额外的样式即可使其看起来像默认情况下的列表一样漂亮。

struct Cell: View {
    @ObservedObject var item: Item
    @State var showExtra = false

    var body: some View {
        VStack {
            Text("tap me")
                .onTapGesture {
                    withAnimation{
                        showExtra.toggle()
                    }
                }
            if showExtra {
                Text("I'm extra text")
            }
        }
    }
}

struct ContenetView: View {
    var items = [ ... ] // your items
    var body: some View {
        ScrollView {
            ForEach(items) { item in
                Cell(item: item)
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)