Использование GeometryReader и предпочтение


GeometryReader - давайте получим geometryProxy вида (в соответствии с родительским представлением / пространством, предоставленным родителем)
Примечание: - дочерний вид остается на своих own (родитель не может заставить их положение или размер)
.preference (key:, value:) - этот модификатор позволяет нам получить некоторые значения (geometryProxy) из представления. так что мы можем получить доступ к прокси геометрии дочернего элемента также из родительского.
комментарий ниже для любого вопроса по этим темам.
вот код, (плюс точка - вы может легко анимировать положение вашего круга (добавив модификатор .animation () . Например, если вы хотите, чтобы ваш круг двигался, когда пользователь нажимает на заголовок)
завершено код
import SwiftUI
struct ContentView: View {
@State var centerCoordinateOfRectangele: MyPreferenceData = MyPreferenceData(x: 0, y: 0)
var body: some View {
ZStack {
VStack {
HStack {
GeometryReader { (geometry) in
TileView(number: 1)
.preference(key: MyPreferenceKey.self, value: MyPreferenceData(x: geometry.frame(in: .named("spaceIWantToMoveMyView")).midX, y: geometry.frame(in: .named("spaceIWantToMoveMyView")).midY))
}
TileView(number: 2)
}.onPreferenceChange(MyPreferenceKey.self) { (value) in
self.centerCoordinateOfRectangele = value
}
HStack {
TileView(number: 3)
TileView(number: 4)
}
}
Circle()
.frame(width: 30, height: 30)
.foregroundColor(Color.red.opacity(0.8))
.position(x: centerCoordinateOfRectangele.x, y: centerCoordinateOfRectangele.y)
}
.coordinateSpace(name: "spaceIWantToMoveMyView") //to get values relative to this layout
// watch where i have use this name
}
}
struct TileView: View{
let number: Int
var body: some View{
GeometryReader { (geometry) in
RoundedRectangle(cornerRadius: 30)
}
}
}
struct MyPreferenceData:Equatable {
let x: CGFloat
let y: CGFloat
}
struct MyPreferenceKey: PreferenceKey {
typealias Value = MyPreferenceData
static var defaultValue: MyPreferenceData = MyPreferenceData(x: 0, y: 0)
static func reduce(value: inout MyPreferenceData, nextValue: () -> MyPreferenceData) {
value = nextValue()
}
}
Объяснение кода ->
модель данных, которую я хочу получить из дочернего представления
struct MyPreferenceData:Equatable {
let x: CGFloat
let y: CGFloat
}
Ключ
struct MyPreferenceKey: PreferenceKey {
typealias Value = MyPreferenceData
static var defaultValue: MyPreferenceData = MyPreferenceData(x: 0, y: 0)
static func reduce(value: inout MyPreferenceData, nextValue: () -> MyPreferenceData) {
value = nextValue()
}
}
defaultValue - SwiftUI используйте это, когда нет явного значения, установленного Reduce () - getCalled, когда SwiftUI хочет дать значения (мы можем использовать модификатор .preference()
во многих представлениях с одним и тем же ключом)
мы добавляем модификатор .preference()
, который мы хотим получить значения