如何在SwiftUI中使用GeometryReader获取和读取文本大小?

如何在SwiftUI中使用GeometryReader获取和读取文本大小?,swift,swiftui,Swift,Swiftui,我试图根据文本字体的大小来读取文本的宽度,因为我们知道GeometryReader占据了所有可能的位置,在这些代码中,它只接受给定的帧大小,我通过了它,但它不接受我文本的大小!我做错了什么?我什么GeometryReader开始只读取我的文本大小!不是他自己的框架宽度 这是我的密码: struct ContentView: View { @State var fontSize: CGFloat = 20.0 var body: some View { Spac

我试图根据文本字体的大小来读取文本的宽度,因为我们知道GeometryReader占据了所有可能的位置,在这些代码中,它只接受给定的帧大小,我通过了它,但它不接受我文本的大小!我做错了什么?我什么GeometryReader开始只读取我的文本大小!不是他自己的框架宽度

这是我的密码:

struct ContentView: View {
    @State var fontSize: CGFloat = 20.0

    var body: some View {
        Spacer()

        textWidthGeometryReader(fontSize: $fontSize)

        Spacer()

        Text("Font size:" + "\(fontSize)")

        Slider(value: $fontSize, in: 20...40, step: 1)
            .padding()

        Spacer()
    }
}

struct textWidthGeometryReader: View {
    @Binding var fontSize: CGFloat

    var body: some View {
        GeometryReader { inSideGeometry in

            Text("width of Text:" + String(format: "%.0f", inSideGeometry.size.width))
                .font(.system(size: fontSize))
                .background(Color.yellow)
                .position(x: inSideGeometry.size.width / 2, y: inSideGeometry.size.height / 2)
        }
        .frame(width: 400, height: 300, alignment: .center)
        .background(Color.gray)
        .cornerRadius(20)
    }
}

您可以使用视图首选项

  • 首先为视图大小创建自定义
    首选项键
  • 创建一个视图,该视图将计算其大小并将其分配给
    ViewSizeKey
  • 在您的视图中使用它们:

  • 查看首选项是一个相当高级的主题。您可以在此处找到更详细的说明:


    在GeometryReader上花了一段时间后,我找到了一种更简单的方法来获取任何视图和文本的大小,我只想回答我的问题,继续尝试我的代码,或者重构它,或者让它变得更小,如果可以的话,我很高兴看到你的方法,这里是我所做的:

    struct ContentView: View {
        @State var sizeOfText: CGSize = .zero
        @State var fontSizeOfText: CGFloat = 20.0
    
        var body: some View {
            Text("Size of Text: " + String(format: "%.0f", sizeOfText.width) + "⭐︎" + String(format: "%.0f", sizeOfText.height))
                .font(.system(size: fontSizeOfText))
                .background(Color.yellow)
                .background(sizeOfView(fontSizeOfText: $fontSizeOfText, sizeOfText: $sizeOfText))
    
            Spacer()
            Text("Font size:" + "\(fontSizeOfText)")
            Slider(value: $fontSizeOfText, in: 20...40, step: 1)
                .padding()
            Spacer()
        }
    }
    
    struct sizeOfView: View {
        @Binding var fontSizeOfText: CGFloat
        @Binding var sizeOfText: CGSize
    
        var body: some View {
            GeometryReader { proxy in
    
                HStack {}
                    .onAppear { sizeOfText = proxy.size }
                    .onChange(of: fontSizeOfText) { _ in sizeOfText = proxy.size }
            }
        }
    }
    

    我找到了解决此问题的另一种方法,这次您可以使用。onReceive也可以,请查看我的代码并改进它,这种方法是3.0.0版!哈哈

    代码:


    你在这里玩得真开心!谢谢如何使GeometryReader进入文本内部,因为我知道该GeometryReader采用文本的大小?@Omid放置在
    背景中的视图与它附加到的视图大小相同。这就是为什么放置在背景中的GeometryReader与文本大小相同。您的所有代码都正常工作,但这并不是将其视为最佳方式的最佳方式!因为文本的宽度是两件事的子项,1-文本字符串,2.文本的字体,所以创建文本的Xcode使用的是父母制作的子项(宽度),为什么苹果会使用它来重新进行已经在文本创建阶段完成的计算?GeometryReader的所有要点是什么?所有答案都在已经完成的文本中。我们只是读取文本的宽度值,我的意思是文本肯定知道它的宽度,为什么我们应该问GeometryReader?@Omid 1)GeometryReader的所有点是什么读取视图的大小。但是,GeometryReader会占用所有可用空间-这就是为什么需要将其放在背景中(与文本大小相同)。2) 我的意思是文本肯定知道它的宽度-不,它不知道。SwiftUI不是UIKit。我知道GeometryReader的一般用法,我说的是一个哲学问题:“GeometryReader的所有要点是什么?”我想告诉大家为什么它应该存在!你说文字不知道自己的长度!我相信文本是一个视图,每个视图都有自己的特殊大小,并且在内存中也有特殊的id来查找它,如果文本作为视图不知道自己的大小,谁知道呢?是的,这也行,首选项方法只是更通用而已。正如您所看到的,您必须使用GeometryReader:)顺便说一句,您可以将
    onAppear
    onChange
    组合起来-请参阅,谢谢,我最初想使用.onReceive实现,但我没有成功!有什么想法吗?你可以做
    onReceive(Just(fontSizeOfText)){…},你需要导入
    Combine
    你可以先
    import Combine
    ,然后在你的代码中
    。onReceive(Just(fontSizeOfText)){in sizeOfText=proxy.size}
    但如果您仍然有问题,请为此创建一个新问题。@pawello2222:请查看我的新答案。
    struct ViewGeometry: View {
        var body: some View {
            GeometryReader { geometry in
                Color.clear
                    .preference(key: ViewSizeKey.self, value: geometry.size)
            }
        }
    }
    
    struct ContentView: View {
        @State var fontSize: CGFloat = 20.0
        @State var textSize: CGSize = .zero
    
        var body: some View {
            Spacer()
            Text("width of Text:" + String(format: "%.0f", textSize.width))
                .font(.system(size: fontSize))
                .background(ViewGeometry())
                .onPreferenceChange(ViewSizeKey.self) {
                    textSize = $0
                }
            Spacer()
            Text("Font size:" + "\(fontSize)")
            Slider(value: $fontSize, in: 20...40, step: 1)
                .padding()
            Spacer()
        }
    }
    
    struct ContentView: View {
        @State var sizeOfText: CGSize = .zero
        @State var fontSizeOfText: CGFloat = 20.0
    
        var body: some View {
            Text("Size of Text: " + String(format: "%.0f", sizeOfText.width) + "⭐︎" + String(format: "%.0f", sizeOfText.height))
                .font(.system(size: fontSizeOfText))
                .background(Color.yellow)
                .background(sizeOfView(fontSizeOfText: $fontSizeOfText, sizeOfText: $sizeOfText))
    
            Spacer()
            Text("Font size:" + "\(fontSizeOfText)")
            Slider(value: $fontSizeOfText, in: 20...40, step: 1)
                .padding()
            Spacer()
        }
    }
    
    struct sizeOfView: View {
        @Binding var fontSizeOfText: CGFloat
        @Binding var sizeOfText: CGSize
    
        var body: some View {
            GeometryReader { proxy in
    
                HStack {}
                    .onAppear { sizeOfText = proxy.size }
                    .onChange(of: fontSizeOfText) { _ in sizeOfText = proxy.size }
            }
        }
    }
    
    class TextModel: ObservableObject
    {
        @Published var sizeOfFont: CGFloat = 20.0
        @Published var sizeOfText: CGSize = .zero
    }
    
    
    
    
    struct ContentView: View
    {
        
        @StateObject var textModel = TextModel()
        
        var body: some View
        {
            
            Spacer()
            
            Text("Size of Text: " + String(format: "%.0f", textModel.sizeOfText.width) + "⭐︎" +  String(format: "%.0f", textModel.sizeOfText.height))
                .font(.system(size: textModel.sizeOfFont))
                .background(Color.yellow)
                .background( sizeOfViewOptionA(textModel: textModel) )
            
            Spacer()
            
            Text("Size of Text: " + String(format: "%.0f", textModel.sizeOfText.width) + "⭐︎" +  String(format: "%.0f", textModel.sizeOfText.height))
                .font(.system(size: textModel.sizeOfFont))
                .background(Color.red)
                .background( sizeOfViewOptionB(textModel: textModel) )
      
            
            Spacer()
            
            Text("Font size:" + "\(textModel.sizeOfFont)")
            
            Slider(value: $textModel.sizeOfFont, in: 20...40, step: 1)
                .padding()
            
            Spacer()
      
        }
      
    }
    
    
    
    struct sizeOfViewOptionA: View
    {
        
        @ObservedObject var textModel: TextModel
    
        var body: some View {
            
            GeometryReader { proxy in
                
                HStack{}
                    .onAppear() {textModel.sizeOfText = proxy.size}
                    .onChange(of: textModel.sizeOfFont) { _ in textModel.sizeOfText = proxy.size}
            }
     
        }
    }
    
    
    struct sizeOfViewOptionB: View
    {
        
        @ObservedObject var textModel: TextModel
    
        var body: some View {
            
            GeometryReader { proxy in
                
                HStack{ Color.clear }
                    .onReceive(textModel.$sizeOfFont) { _ in textModel.sizeOfText = proxy.size}
            }
     
        }
    }