Currently, I am using multiple Text
s in a horizontal stackview, to achieve animation of substring.
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()
}
To keep it all on one line with a consistent font size, try these changes:
.minimumScaleFactor
to the HStack
..scaledToFit
to the HStack
too.Other suggestions:
.font
to the HStack
, instead of to each individual Text
item..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..animation
modifier is deprecated. Add a value
parameter to correct this.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
}
}