我不是SwiftUI的资深人士,但我已经发布了一些中等复杂度的应用程序。不过,我不能说我完全理解它,我希望知识更深的人可以对此问题有所启发:
我有一些想要打开和关闭的内容,与。sheet()不同,但我想对其进行更多控制。这是一些“重构”的代码,但是它应该能够捕获本质:
struct ContentView: View {
@State private var isShown = false
var body: some View {
GeometryReader { g in
VStack {
ZStack(alignment: .top) {
// This element "holds" the size
// while the content is hidden
Color.clear
// Content to be toggled
if self.isShown {
ScrollView {
Rectangle()
.aspectRatio(1, contentMode: .fit)
.frame(width: g.size.width) // This is a "work-around"
} // ScrollView
.transition(.move(edge: .bottom))
.animation(.easeOut)
}
} // ZStack
// Button to show / hide the content
Button(action: {
self.isShown.toggle()
}) {
Text(self.isShown ? "Hide" : "Show")
}
} // VStack
} // GeometryReader
}
}
它的作用是,它打开和关闭某些内容块(在这里由ScrollView中的Rectangle表示)。发生这种情况时,内容视图会通过从底部移动一些动画而转变。当再次轻击按钮时,情况恰好相反。
此特定代码段按预期工作,但仅由于此行:
.frame(width: g.size.width) // This is a "work-around"
反过来,则需要额外的GeometryReader,否则,内容的宽度会设置动画,产生不想要的效果(我发现的另一个“修复”是使用。fixedSize()修饰符,但要产生合理的效果,它要求内容采用自己的宽度,例如Text)
我的明智的问题是:是否可以在不使用这样的“修复程序”的情况下很好地转换封装在ScrollView中的内容?或者,是否有更优雅的解决方案?
快速补充@Asperi回答之后的问题:内容应保持可动画显示。你是我唯一的希望,
– Baglan
这里是一个解决方案(更新为body
,没有GeometryReader
)。经过Xcode 11.4 / iOS 13.4的测试]
var body: some View {
VStack {
ZStack(alignment: .top) {
// This element "holds" the size
// while the content is hidden
Color.clear
// Content to be toggled
if self.isShown {
ScrollView {
Rectangle()
.aspectRatio(1, contentMode: .fit)
.animation(nil) // << here !!
} // ScrollView
.transition(.move(edge: .bottom))
.animation(.easeOut)
}
} // ZStack
// Button to show / hide the content
Button(action: {
self.isShown.toggle()
}) {
Text(self.isShown ? "Hide" : "Show")
}
} // VStack
}