-3

Currently, I am using multiple Texts in a horizontal stackview, to achieve animation of substring.

enter image description here

As you can see in the above animation, the text

- conversation
- meeting
- lecture

are animated.

However, there shortcoming of such an approach.

Text size is not consistent among different Text block. The following Text block are having different text size.

- Transform
- conversation/ meeting/ lecture
- to Quick Note

Any idea how we can achieve, so that all text blocks have same text size so that they appear like 1 sentence?

Or, how we can make the text blocks having constant text size, but able to perform line wrapping to next line, so that they appear like 1 sentence?

Currently, this is the code snippet I am using.

import SwiftUI

struct ContentView: View {
    var array = ["lecture", "conversation", "meeting"]
    
    @State var currentIndex : Int = 0
    @State var firstString : String = ""

    var body: some View {

        VStack {
            HStack {
                Text("Transform")
                    .lineLimit(1)
                    .minimumScaleFactor(0.5)
                    .font(.title)
                
               Text(firstString)
                    .lineLimit(1)
                    .minimumScaleFactor(0.5)
                    .font(.title)
                    .transition(AnyTransition.opacity.animation(.easeInOut(duration:1.0)))
                    .background(.yellow)
                
                Text("to Quick Note")
                    .lineLimit(1)
                    .minimumScaleFactor(0.5)
                    .font(.title)
            }.padding()
        }
        .animation(.default)
        .onAppear {
            firstString = array[0]
            
            let timer = Timer.scheduledTimer(withTimeInterval: 2.0, repeats: true) { _ in
                if currentIndex == array.count - 1 {
                    self.firstString = array[0]
                    currentIndex = 0
                }
                else {
                    self.firstString = array[currentIndex+1]
                    currentIndex += 1
                }
            }
        }
    }
}

#Preview {
    ContentView()
}
1
  • Question seems reasonable to me and the code works for reproducing the problem, a reason for the downvotes is not clear to me. Commented Dec 15, 2024 at 12:56

1 Answer 1

2

To keep it all on one line with a consistent font size, try these changes:

  • Move the modifier .minimumScaleFactor to the HStack.
  • Apply .scaledToFit to the HStack too.

Other suggestions:

  • You only really need one state variable, not two.
  • It is simpler to apply modifiers like .font to the HStack, instead of to each individual Text item.
  • The .transition modifier is redundant, because it is the content of the Text that is changing, no views are being inserted or removed. However, you could consider using .contentTransition if you don't want the default .opacity transition to be seen when the content changes.
  • The way you are using the .animation modifier is deprecated. Add a value parameter to correct this.
  • See this answer for some better ways of triggering the timed updates.

Here is an updated version of the example. This also illustrates how to use task(id:priority:_:) for the timed animation.

@State var currentIndex : Int = 0
//@State var firstString : String = ""
VStack {
    HStack {
        Text("Transform")

        Text(array[currentIndex])
            .background(.yellow)

        Text("to Quick Note")
    }
    .lineLimit(1)
    .font(.title)
    .minimumScaleFactor(0.5)
    .scaledToFit()
    .padding()
}
.animation(.default, value: currentIndex)
.task(id: currentIndex) {
    try? await Task.sleep(for: .seconds(2))
    if currentIndex == array.count - 1 {
        currentIndex = 0
    } else {
        currentIndex += 1
    }
}

Animation

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.