Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

Tags:

swift

swiftui

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.

enter image description here

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)
    }
}
like image 384
ios coder Avatar asked Oct 20 '20 20:10

ios coder


People also ask

How do I change font size in SwiftUI?

System Fontsystem(size:weight:design:) method. This method lets us specify a fixed font size that we want. Here is an example where we set the font for the second text to a fixed size of 36 points.

What is the purpose of GeometryReader?

According to Apple, GeometryReader is "a container view that defines its content as a function of its own size and coordinate space." Like most everything in SwiftUI, GeometryReader is a view but with the added benefit of exposing additional information to its child views.


1 Answers

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
like image 121
pawello2222 Avatar answered Sep 22 '22 09:09

pawello2222