问题
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.
- First create a custom
PreferenceKeyfor the view size:
struct ViewSizeKey: PreferenceKey {
static var defaultValue: CGSize = .zero
static func reduce(value: inout CGSize, nextValue: () -> CGSize) {
value = nextValue()
}
}
- 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)
}
}
}
- 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