[英]How we can get and read size of a Text with GeometryReader in 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)
}
}
您可以使用查看首选项。
PreferenceKey
:struct ViewSizeKey: PreferenceKey {
static var defaultValue: CGSize = .zero
static func reduce(value: inout CGSize, nextValue: () -> CGSize) {
value = nextValue()
}
}
ViewSizeKey
: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()
}
}
查看首选项是一个相当高级的主题。 你可以在这里找到更详细的解释:
在 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 版! 哈哈
代码:
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}
}
}
}
另一种方法是根本不渲染(这将允许您从无状态代码(如扩展)中进行计算):
extension String
{
func sizeUsingFont(usingFont font: UIFont) -> CGSize
{
let fontAttributes = [NSAttributedString.Key.font: font]
return self.size(withAttributes: fontAttributes)
}
}
并像这样使用它:
// 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))
我使用的来源: 如何在 SwiftUI 中动态计算字符串的宽度
如果您仍然决定使用 GeometryReader,请记住您可以将 GeometryReader 放入 .background() 并将其保存到状态 var on-appear 或 on-whatever event 适合您:
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)
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.