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

use*_*ser 5 swift swiftui

我正在尝试根据文本字体的大小读取文本的宽度,正如我们所知,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)
    }
}
Run Code Online (Sandbox Code Playgroud)

Sha*_*ybc 6

另一种方法是根本不渲染(这将允许您从无状态代码(如扩展)进行计算):

extension String
{
   func sizeUsingFont(usingFont font: UIFont) -> CGSize
    {
        let fontAttributes = [NSAttributedString.Key.font: font]
        return self.size(withAttributes: fontAttributes)
    }
}
Run Code Online (Sandbox Code Playgroud)

并像这样使用它:

// calculate render width and height of text using provided font (without actually rendering)
let sizeOfText: CGSize = "test string".sizeUsingFont(usingFont: UIFont.systemFont(ofSize: 40, weight: UIFont.Weight.bold))
Run Code Online (Sandbox Code Playgroud)

我使用的来源: 如何在 SwiftUI 中动态计算字符串的宽度

如果您仍然决定使用 GeometryReader,请记住您可以将 GeometryReader 放入 .background() 中,并将其保存到出现或任何适合您的事件时的状态变量:

import Foundation
import SwiftUI

struct TestView: View
{
    @State var sizeOfText: CGSize = CGSize(width: 0, height: 0)
    
    var body: some View
    {
        Text("Hello again")
            .font(Font.system(size:60, design: Font.Design.rounded))
            .background(GeometryReader { (geometryProxy : GeometryProxy) in
                HStack {}
                .onAppear {
                    sizeOfText = geometryProxy.size
                    print("sizeOfText: \(sizeOfText)")
                }
            })
            .offset(x: sizeOfText.width, y: sizeOfText.height)
    }
}
Run Code Online (Sandbox Code Playgroud)


paw*_*222 5

您可以使用查看首选项。

  1. 首先PreferenceKey为视图大小创建自定义:
struct ViewSizeKey: PreferenceKey {
    static var defaultValue: CGSize = .zero

    static func reduce(value: inout CGSize, nextValue: () -> CGSize) {
        value = nextValue()
    }
}
Run Code Online (Sandbox Code Playgroud)
  1. 创建一个视图,它将计算其大小并将其分配给ViewSizeKey
struct ViewGeometry: View {
    var body: some View {
        GeometryReader { geometry in
            Color.clear
                .preference(key: ViewSizeKey.self, value: geometry.size)
        }
    }
}
Run Code Online (Sandbox Code Playgroud)
  1. 在您的视图中使用它们:
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()
    }
}
Run Code Online (Sandbox Code Playgroud)

查看首选项是一个相当高级的主题。你可以在这里找到更详细的解释: