在 SwiftUI 中缩小文本的字体大小以使其长度适合其他文本

Scaling down a text's font size to fit its length to another text in SwiftUI

提问人:Khashayar 提问时间:9/5/2021 更新时间:8/23/2022 访问量:581

问:

请考虑以下代码:

VStack{
    Text("A reference text")
    Text("(Adjust the length of this line to match the one above)")
}

我希望第二个字体大小缩小,正好是上面句子的长度。我已经试过了:Text()

Text("(Adjust the length of this line to match the one above)")
     .scaledToFit()
     .minimumScaleFactor(0.01)

但似乎行不通。我怎样才能做到这一点?

Swift SwiftUI

评论


答:

1赞 lorem ipsum 9/5/2021 #1

您需要获取参考视图的大小

struct ScaledTextView: View {
    @State var textSize: CGSize =  CGSize.zero
    var body: some View {
        VStack{
            Text("A reference text")
                .viewSize(viewSize: $textSize) //Get initial size and any changes
            Text("(Adjust the length of this line to match the one above)")
            //If you want it to be a single line set the limit
            //.lineLimit(1)
            
            //Set the dependent's view frame, you can just set the width if you want, height is optional
                .frame(width: textSize.width, height: textSize.height)
                .scaledToFit()
                .minimumScaleFactor(0.01)
        }
    }
}
//Make it reusable and keep the view clean
extension View{
    func viewSize(viewSize: Binding<CGSize>) -> some View{
        return self.background(
            //Get the size of the View
            GeometryReader{geo in
                Text("")
                //detects changes such as landscape, etc
                    .onChange(of: geo.size, perform: {value in
                        //set the size
                        viewSize.wrappedValue = value
                    })
                //Initial size
                    .onAppear(perform: {
                        //set the size
                        viewSize.wrappedValue = geo.size
                    })
            }
        )
    }
}
2赞 Asperi 9/5/2021 #2

这是可能的简单方法(使用 Xcode 13.4 / iOS 15.5 测试)

更新:发现更简单,基于相同的概念(也适用于动态大小)

Text("A reference text")
    .padding(.bottom)     // << spacing can be tuned 
    .overlay(
        Text("(Adjust the length of this line to match the one above)")
            .scaledToFit()
            .minimumScaleFactor(0.01)
    , alignment: .bottom)     // << important !!

源语言:

VStack {
    let ref = "A reference text"
    let target = "(Adjust the length of this line to match the one above)"
    Text(ref)
    Text(ref).opacity(0)
        .overlay(Text(target)
            .scaledToFit()
            .minimumScaleFactor(0.01)
        )
}

demo

1赞 George 9/5/2021 #3

这是一种不固定较小文本高度的方法。

struct ContentView: View {
    @State private var width: CGFloat?

    var body: some View {
        VStack {
            Text("A reference text")
                .background(
                    GeometryReader { geo in
                        Color.clear.onAppear { width = geo.size.width }
                    }
                )

            Text("(Adjust the length of this line to match the one above)")
                .scaledToFit()
                .minimumScaleFactor(0.01)
        }
        .frame(width: width)
        .border(Color.red)
    }
}

结果:

Result