Search code examples
buttontextstylesswiftui

SwiftUI: Resize text to fit button


I am updating button text based on values in a database and as these values may be very long or very short, I want the button size to remain constant and the text to resize dynamically depending on how big the value is, so it remains within the button and not truncated (The values will be sentences, it is a language learning app). I basically want to give the font size a minimum possible value and a maximum possible value.

I know how to do this in Android Studio.

autoSizeMinTextSize=14sp
autoSizeMaxTestSize=20sp

But when I tried to use suggestions like a large font size with minimumScaleFactor, it doesn't work. It just makes the text incredibly small.

Here is my button style.

struct SoundButton: ButtonStyle {

    func makeBody(configuration: Self.Configuration) -> some View {
        configuration.label
            .foregroundColor(Color.black)
            .multilineTextAlignment(.center)
            .font(.custom("arial", size: 20))
            .frame(maxWidth: .infinity, maxHeight: .infinity)
            .background(configuration.isPressed ? LinearGradient(gradient: Gradient(colors: [Color("DarkestGreen"), Color("LightGreen")]), startPoint: .top, endPoint: .bottom):LinearGradient(gradient: Gradient(colors: [Color("DarkGreen"), Color("LightGreen")]), startPoint: .top, endPoint: .bottom))
            .cornerRadius(10)
            .shadow(radius: 3.0)
            .overlay(
                RoundedRectangle(cornerRadius: 10)
                    .stroke(Color.white, lineWidth:2))
            .padding(2)
            .scaleEffect(configuration.isPressed ? 0.975 : 1.0)
    }
}

And here is the button code.

                        Button(action: {
                            playSound(sound: "\(self.category)_audio1", type: "mp3")
                            self.translation = self.btns[1][1]
                        }) {
                            if(gotValues==true) {
                                Text("\(self.btns[1][0])")
                            } else {
                                Text("\(self.btn1)")
                            }
                        }

Here is what my screen looks like in the app.

enter image description here

What can I add to this to achieve the desired effect? Thank you.

Also, here is the working android version.

enter image description here


Solution

  • As far as I understood your goal the following should give you required effect (or sort of)...

    Tested with Xcode 11.4 / iOS 13.4

    demo

    configuration.label
        .padding(.horizontal, 8).lineLimit(1).minimumScaleFactor(0.4) // << this place !
        .foregroundColor(Color.white)