SwiftUI ошибочное выравнивание оверлея по вертикали при использовании GeometryReader
У меня есть вид наложения, который я хочу, чтобы он обнимал верхний край его родительского вида (выровнен по вертикали по верху, а не по центру, см. Снимок B), и у меня есть возможность частично скрывать его при нажатии (переместите его вверх, чтобы он не t затемнять его родительский вид, но при этом иметь видимую часть, скажем, 64 пикселя, чтобы его все еще можно было вернуть в исходное положение, см. снимок C). Проблема в том, что когда я используюGeometryReader
чтобы получить высоту наложения, которую я пытаюсь переместить, наложение появляется в центре представления изначально (см. снимок A). И если я не использую считыватель геометрии, я не знаю, насколько сместить вид наложения:
@State var moveOverlay = false
var body : some View {
VStack {
ForEach(0...18, id: \.self) { _ in
Text("This is the background... This is the background... This is the background... This is the background... ")
}
}
.overlay(VStack {
GeometryReader { proxy in
Text("This is the overlay text snippet sentence that is multiline...\nThis is the overlay text snippet sentence that is multiline...\nThis is the overlay text snippet sentence that is multiline...\nThis is the overlay text snippet sentence that is multiline...\nThis is the overlay text snippet sentence that is multiline...\nThis is the overlay text snippet sentence that is multiline...\n")
.lineLimit(9)
.background(Color.gray)
.padding(32)
.frame(maxWidth: nil)
.offset(x: 0, y: self.moveOverlay ? -proxy.size.height + 128 + 64 : 0)
.onTapGesture {
self.moveOverlay = !self.moveOverlay
}
}
Spacer()
})
}
Не уверен, почему считыватель геометрии так влияет на макет.
(A) Вот как это выглядит с кодом считывателя геометрии:
(B) Если я удалю код считывателя геометрии, я получу желаемый эффект:
(C) И вот как я хочу, чтобы наложение было перемещено наверх:
РЕДАКТИРОВАТЬ: приведенный выше код создает макет (A). Мне нужен макет (B), который я получаю, если опускаю код считывателя геометрии.
2 ответа
Ну... все еще не уверен, но вот подход
Протестировано с Xcode 11.4 / iOS 13.4
.overlay(
ZStack(alignment: .top) {
Color.clear
Text("This is the overlay text snippet sentence that is multiline...\nThis is the overlay text snippet sentence that is multiline...\nThis is the overlay text snippet sentence that is multiline...\nThis is the overlay text snippet sentence that is multiline...\nThis is the overlay text snippet sentence that is multiline...\nThis is the overlay text snippet sentence that is multiline...\n")
.lineLimit(9)
.background(Color.gray)
.alignmentGuide(.top) { self.hideOverlay ? $0.height * 3/2 : $0[.top] - 64 }
.onTapGesture {
withAnimation(Animation.spring()) {
self.hideOverlay.toggle()
}
}
})
Вы можете использовать второй аргумент в func overlay<Overlay>(_ overlay: Overlay, alignment: Alignment = .center)
для этого выровняйте его по верхнему краю и переместив вверх или вниз со смещением в зависимости от режима.
struct AlignmentView: View {
@State var hideOverlay = false
var body : some View {
GeometryReader{ proxy in
VStack {
ForEach(0...18, id: \.self) { _ in
Text("This is the background... This is the background... This is the background... This is the background... ")
}
}
.overlay(
Text("This is the overlay text snippet sentence that is multiline...\nThis is the overlay text snippet sentence that is multiline...\nThis is the overlay text snippet sentence that is multiline...\nThis is the overlay text snippet sentence that is multiline...\nThis is the overlay text snippet sentence that is multiline...\nThis is the overlay text snippet sentence that is multiline...\n")
.lineLimit(9)
.background(Color.gray)
.frame(maxWidth: nil)
.offset(x: 0, y: self.hideOverlay ? -proxy.size.height / 5.0 : 50)
.onTapGesture {
withAnimation {
self.hideOverlay.toggle()
}
},
alignment: .top)
}
}
}