How we can get and read size of a Text with GeometryReader in SwiftUI?

无人久伴 提交于 2021-02-01 20:48:34

问题


I am trying to read the width of my Text depending on size of Text Font, As we know GeometryReader takes all possible given place to him, in this codes it just take himself the given frame size, that I passed it, but it does not take size of my Text! what I am doing Wrong? I what GeometryReader start reading my Text size only! not himself frame width.

Here is my code:

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)
    }
}

回答1:


You can use view preferences.

  1. First create a custom PreferenceKey for the view size:
struct ViewSizeKey: PreferenceKey {
    static var defaultValue: CGSize = .zero

    static func reduce(value: inout CGSize, nextValue: () -> CGSize) {
        value = nextValue()
    }
}
  1. Create a view which will calculate its size and assign it to the ViewSizeKey:
struct ViewGeometry: View {
    var body: some View {
        GeometryReader { geometry in
            Color.clear
                .preference(key: ViewSizeKey.self, value: geometry.size)
        }
    }
}
  1. Use them in your view:
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()
    }
}

View Preferences is quite an advanced topic. You can find a more detailed explanation here:

  • The magic of view preferences in SwiftUI
  • Inspecting the View Tree – Part 1: PreferenceKey



回答2:


After spending time on GeometryReader I find a easer way to get the size of any view also Text and I just wanted Answer my Question, Go ahead try my Code or Refactor it or make it more smaller if you can, I am pleased to see your way, here what I made:

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 }
        }
    }
}



回答3:


I found another way to solving this issue, this time you are able to work with .onReceive as well, see my code and make it better, this way is Version 3.0.0! LoL

Code:

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}
        }
 
    }
}


来源:https://stackoverflow.com/questions/64452647/how-we-can-get-and-read-size-of-a-text-with-geometryreader-in-swiftui

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!