SwiftUI 表单中的动态行高

rus*_*ish 2 forms layout swiftui

我正在向 SwiftUI 表单添加控件以帮助用户输入数据(并限制条目!)。尽管 Forms 有很多值得喜欢的地方,但我发现在该容器之外运行良好的东西在容器内却会发生非常意想不到的事情,并且如何弥补这一点并不总是显而易见的。

计划是将数据字段显示为单行。当点击该行时,控件从数据字段后面滑出 - 该行需要扩展(高度)以容纳控件。

我正在使用 Swift Playgrounds 来开发概念验证(或者在我的例子中失败)。这个想法是使用 ZStack,它可以通过覆盖视图并给它们一个不同的 zIndex 并在点击数据字段视图时应用偏移量来实现漂亮的滑动动画。听起来很简单,但是当 ZStack 展开时,Form 行当然不会展开。

在扩展时调整 ZStack 的框架会导致填充发生各种奇怪的变化(或者至少看起来像这样),这可以通过抵消“顶部”视图来补偿,但这会导致其他不可预测的行为。指针和想法感激地接受。

导入 SwiftUI

struct MyView: View {
    @State var isDisclosed = false

    var body: some View {
        Form { 
            Spacer()

            VStack { 
                ZStack(alignment: .topLeading) {
                    Rectangle()
                        .fill(Color.red)
                        .frame(width: 100, height: 100)
                        .zIndex(1)
                        .onTapGesture { self.isDisclosed.toggle() }

                    Rectangle()
                        .fill(Color.blue)
                        .frame(width: 100, height: 100)
                        .offset(y: isDisclosed ? 50 : 0)
                        .animation(.easeOut)
                }
            }

            Spacer()
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

折叠堆栈 折叠堆栈

扩展堆栈 - 视图与相邻行重叠 扩展堆栈 - 视图与相邻行重叠

展开时调整 ZStack 垂直框架时的结果 - 顶部填充增加 展开时调整 ZStack 垂直框架时的结果 - 顶部填充增加

Asp*_*eri 5

这是具有流畅行高变化的可能解决方案(使用AnimatingCellHeight从我在SwiftUI 中的解决方案中获取的修饰符 - 在列表中的视图内触发的动画也不会为列表设置动画)。

使用 Xcode 11.4 / iOS 13.4 进行测试

演示

struct MyView: View {
    @State var isDisclosed = false

    var body: some View {
        Form {
            Spacer()

            ZStack(alignment: .topLeading) {
                Rectangle()
                    .fill(Color.red)
                    .frame(width: 100, height: 100)
                    .zIndex(1)
                    .onTapGesture { withAnimation { self.isDisclosed.toggle() } }

                HStack {
                    Rectangle()
                        .fill(Color.blue)
                        .frame(width: 100, height: 100)
                }.frame(maxHeight: .infinity, alignment: .bottom)
            }
            .modifier(AnimatingCellHeight(height: isDisclosed ? 150 : 100))

            Spacer()
        }
    }
}
Run Code Online (Sandbox Code Playgroud)