16

I have a Text that I want to modify with a .minimumScaleFactor(0.1) when the length of its string extends outside the view. However, the scaling applies every time, even when the original font size would be perfectly fine.

My view is structured thusly:

        VStack(alignment: .center, spacing: 0) {
            HStack {
                Image("medal \(place)").resizable()
                    .foregroundColor(color)
                    .frame(width: 40, height: 40)
                Spacer()
                Text(username)
                    .font(.bold(16))
                    .lineLimit(1)
                    .minimumScaleFactor(0.1)
                    .frame(alignment: .trailing)
                    .foregroundColor(Color("mediumTextColor"))
            }
            Spacer()
            Text(score)
                .font(.extraBold(60))
                .foregroundColor(color)
                .lineLimit(1)
                .minimumScaleFactor(0.7)

            Spacer()
        }
        .frame(height: 96)
        .padding(10)
        .cornerRadius(16)
        .overlay(RoundedRectangle(cornerRadius: 16)
        .stroke(color, lineWidth: 2))
A. Lucas
  • 261
  • 3
  • 11
  • 2
    Did you find a solution to this? I'm facing the same problem. You commented on an answer saying "It actually needed up working when I embedded the whole thing in a GeometryReader" — can you provide example code showing how you solved it? – gohnjanotis Nov 07 '19 at 00:09
  • 1
    I posted how I solved this... – A. Lucas Nov 07 '19 at 16:00

6 Answers6

11

A continuation of answer above.

What is important is the order in which the modifiers are applied:

Text("This is a really long sentence.") 
   .minimumScaleFactor(0.5)                
   .font(.custom("OpenSans", size: 15))
   .lineLimit(1)
   .layoutPriority(1)

There isn't a need for the GeometryReader unless you need it for something else

Alexander
  • 1,424
  • 18
  • 23
  • I have 3 `Texts with different `Font`s embedded in an `HStack` and setting the `minimumScaleFactor` on each `Text` would be a pain, but gladly, setting `minimumScaleFactor` and `lineLimit` on the `HStack` works perfectly fine, even if the `font` is set differently for each `Text`. – Dávid Pásztor Jul 01 '20 at 10:47
  • Why? Where can we read up to find out how modifier order affects font and minimumScale to understand better? – whitneyland May 05 '22 at 22:20
5

Adding .lineLimit(1) to the Text will work well.

Xcode: 11.3.1

mishimay
  • 4,237
  • 1
  • 27
  • 23
4

Important for that minimumScaleFactor() only does its job when it is needed, is the combination of .minimumScaleFactor AND .lineLimit(1); otherwise it will not work. layoutPriority(1) is not the key here.

Example - this works; Scale is only applied when needed:

Text("Something").minimumScaleFactor(0.5).lineLimit(1)
NeoLeon
  • 191
  • 1
  • 7
3

Adding a GeometryReader around the VStack that my two Text views were in solved this. As requested by @gohnjanotis:

GeometryReader { proxy in
    VStack(alignment: .center, spacing: 0) {
        HStack {
            Image("medal \(self.place)").resizable()
                .foregroundColor(self.color)
                .frame(width: 40, height: 40)

            Spacer()
            Text(self.username)
                .minimumScaleFactor(0.1)
                .font(.bold(16))
                .lineLimit(1)
                .frame(alignment: .trailing)
                .foregroundColor(Color("mediumTextColor"))
                .layoutPriority(1)

        }
        .padding(.top, 10)
        .padding(.horizontal, 10)
        Spacer()
        Text(self.score)
            .font(.extraBold(60))
            .foregroundColor(self.color)
            .lineLimit(1)
            .minimumScaleFactor(0.1)
            .layoutPriority(1)
            .padding(.horizontal, 10)
            .padding(.bottom, 10)
            .offset(y: -10)
    }
    .frame(width: proxy.size.width, height: proxy.size.height, alignment: .top)
}
.frame(maxHeight: 130)
A. Lucas
  • 261
  • 3
  • 11
1

After trying to figuring this out for a long while... playing with minimumScaleFactor, LineLimit, layoutPriority... I found out that using .frame() helps solve my problem.

My problem is that minimumScaleFactor applies to Text even if it is not needed.

Applying .frame() ad the last line solve my problem.

Something like this...

GeometryReader { geometry in
    VStack{
        
        Text("Hello")
            .foregroundColor(Color.Black)
            .font(.system(size: 50))
            .minimumScaleFactor(0.1)
            .lineLimit(1)
            .frame(height: geometry.size.height)
    }
}
Boon
  • 111
  • 1
  • 5
0

Add .layoutPriority(1) modifier to your Text to make sure it takes the space if there is any.

Ahmed Allam
  • 104
  • 8