是否可以将 GeometryReader 的值传递给 @Observableobject
Is it possible to pass the values of GeometryReader to a @Observableobject
我需要根据设备的尺寸和屏幕的宽度进行计算。
struct TranslatorView: View {
@ObservedObject var settings = TranslationViewModel(spacing: 4, charSize: 20)
var body: some View {
GeometryReader { geometry in
VStack{
TextField("Enter your name", text:self.$settings.translateString)
}
}
}
}
下面可以看到我的ObservableObject
class TranslationViewModel: ObservableObject {
@Published var translateString = ""
var ScreenSize : CGFloat = 0
var spacing : CGFloat = 4
var charSize : CGFloat = 20
init(spacing: CGFloat, charSize : CGFloat) {
self.spacing = spacing
self.charSize = charSize
}
}
我需要一种方法将 geometry.size.width
传递给我的 ScreenSize
属性 但不知道该怎么做。
最简单的方法是在 ObservableObject
中使用 setter 方法,其中 returns 和 EmptyView
.
import SwiftUI
struct TranslatorView: View {
@ObservedObject var settings = TranslationViewModel(spacing: 4, charSize: 20)
var body: some View {
GeometryReader { geometry in
VStack{
self.settings.passWidth(geometry: geometry)
TextField("Enter your name", text:self.$settings.translateString)
}
}
}
}
class TranslationViewModel: ObservableObject {
@Published var translateString = ""
var ScreenSize : CGFloat = 0
var spacing : CGFloat = 4
var charSize : CGFloat = 20
init(spacing: CGFloat, charSize : CGFloat) {
self.spacing = spacing
self.charSize = charSize
}
func passWidth(geometry: GeometryProxy) -> EmptyView {
self.ScreenSize = geometry.size.width
return EmptyView()
}
}
然后你可以围绕 GeometryReader
实现一个包装器,采用 content: () -> Content
和一个每次 GeometryReader
重新渲染时都会执行的闭包,你可以在其中更新任何你想要的东西。
import SwiftUI
struct TranslatorView: View {
@ObservedObject var settings = TranslationViewModel(spacing: 4, charSize: 20)
var body: some View {
GeometryReaderEasy(callback: {
self.settings.ScreenSize = [=11=].size.width
}) { geometry in
TextField("Enter your name", text:self.$settings.translateString)
}
}
}
struct GeometryReaderEasy<Content: View>: View {
var callback: (GeometryProxy) -> ()
var content: (GeometryProxy) -> (Content)
private func setGeometry(geometry: GeometryProxy) -> EmptyView {
callback(geometry)
return EmptyView()
}
var body: some View {
GeometryReader { geometry in
VStack{
self.setGeometry(geometry: geometry)
self.content(geometry)
}
}
}
}
您可以在 View
上使用一个简单的扩展来允许在构建视图时执行任意代码。
extension View {
func execute(_ closure: () -> Void) -> Self {
closure()
return self
}
}
然后
var body: some View {
GeometryReader { proxy
Color.clear.execute {
self.myObject.useProxy(proxy)
}
}
}
另一种选择是使用 .onAppear
设置值
struct TranslatorView: View {
@ObservedObject var settings = TranslationViewModel(spacing: 4, charSize: 20)
var body: some View {
GeometryReader { geometry in
VStack{
TextField("Enter your name", text:self.$settings.translateString)
} .onAppear {
settings.ScreenSize = geometry.size.width
}
}
}
}
我需要根据设备的尺寸和屏幕的宽度进行计算。
struct TranslatorView: View {
@ObservedObject var settings = TranslationViewModel(spacing: 4, charSize: 20)
var body: some View {
GeometryReader { geometry in
VStack{
TextField("Enter your name", text:self.$settings.translateString)
}
}
}
}
下面可以看到我的ObservableObject
class TranslationViewModel: ObservableObject {
@Published var translateString = ""
var ScreenSize : CGFloat = 0
var spacing : CGFloat = 4
var charSize : CGFloat = 20
init(spacing: CGFloat, charSize : CGFloat) {
self.spacing = spacing
self.charSize = charSize
}
}
我需要一种方法将 geometry.size.width
传递给我的 ScreenSize
属性 但不知道该怎么做。
最简单的方法是在 ObservableObject
中使用 setter 方法,其中 returns 和 EmptyView
.
import SwiftUI
struct TranslatorView: View {
@ObservedObject var settings = TranslationViewModel(spacing: 4, charSize: 20)
var body: some View {
GeometryReader { geometry in
VStack{
self.settings.passWidth(geometry: geometry)
TextField("Enter your name", text:self.$settings.translateString)
}
}
}
}
class TranslationViewModel: ObservableObject {
@Published var translateString = ""
var ScreenSize : CGFloat = 0
var spacing : CGFloat = 4
var charSize : CGFloat = 20
init(spacing: CGFloat, charSize : CGFloat) {
self.spacing = spacing
self.charSize = charSize
}
func passWidth(geometry: GeometryProxy) -> EmptyView {
self.ScreenSize = geometry.size.width
return EmptyView()
}
}
然后你可以围绕 GeometryReader
实现一个包装器,采用 content: () -> Content
和一个每次 GeometryReader
重新渲染时都会执行的闭包,你可以在其中更新任何你想要的东西。
import SwiftUI
struct TranslatorView: View {
@ObservedObject var settings = TranslationViewModel(spacing: 4, charSize: 20)
var body: some View {
GeometryReaderEasy(callback: {
self.settings.ScreenSize = [=11=].size.width
}) { geometry in
TextField("Enter your name", text:self.$settings.translateString)
}
}
}
struct GeometryReaderEasy<Content: View>: View {
var callback: (GeometryProxy) -> ()
var content: (GeometryProxy) -> (Content)
private func setGeometry(geometry: GeometryProxy) -> EmptyView {
callback(geometry)
return EmptyView()
}
var body: some View {
GeometryReader { geometry in
VStack{
self.setGeometry(geometry: geometry)
self.content(geometry)
}
}
}
}
您可以在 View
上使用一个简单的扩展来允许在构建视图时执行任意代码。
extension View {
func execute(_ closure: () -> Void) -> Self {
closure()
return self
}
}
然后
var body: some View {
GeometryReader { proxy
Color.clear.execute {
self.myObject.useProxy(proxy)
}
}
}
另一种选择是使用 .onAppear
设置值struct TranslatorView: View {
@ObservedObject var settings = TranslationViewModel(spacing: 4, charSize: 20)
var body: some View {
GeometryReader { geometry in
VStack{
TextField("Enter your name", text:self.$settings.translateString)
} .onAppear {
settings.ScreenSize = geometry.size.width
}
}
}
}