SwiftUI:动画文本颜色 - foregroundColor()
SwiftUI: Animate Text color - foregroundColor()
我一直在尝试为 UI 的各个部分设置动画,但似乎您无法为 SwiftUI 文本的前景色设置动画?我想在状态改变时平滑地切换一些文本的颜色。如果我为文本周围视图的背景颜色设置动画效果很好,但前景色不起作用。有没有人幸运地为这样的变化设置动画?不确定这是 Xcode 测试版错误还是它的预期功能...
Text(highlightedText)
.foregroundColor(color.wrappedValue)
.animation(.easeInOut)
// Error: Cannot convert value of type 'Text' to closure result type '_'
Text
的颜色 属性 在 SwiftUI
或 UIKit
中不可设置动画。 但你可以达到你需要的结果:
struct ContentView: View {
@State var highlighted = false
var body: some View {
VStack {
ZStack {
// Highlighted State
Text("Text To Change Color")
.foregroundColor(.red)
.opacity(highlighted ? 1 : 0)
// Normal State
Text("Text To Change Color")
.foregroundColor(.blue)
.opacity(highlighted ? 0 : 1)
}
Button("Change") {
withAnimation(.easeIn) {
self.highlighted.toggle()
}
}
}
}
}
您可以将此功能封装在自定义 View
中并在您喜欢的任何地方使用它。
SwiftUI 中有一个很好的协议,可让您为任何内容设置动画。即使是不可动画的东西! (例如文字颜色)。该协议称为 AnimatableModifier。
如果您想了解更多信息,我写了一篇完整的文章来解释它是如何工作的:https://swiftui-lab.com/swiftui-animations-part3/
下面是一个关于如何实现这种视图的示例:
AnimatableColorText(from: UIColor.systemRed, to: UIColor.systemGreen, pct: flag ? 1 : 0) {
Text("Hello World").font(.largeTitle)
}.onTapGesture {
withAnimation(.easeInOut(duration: 2.0)) {
self.flag.toggle()
}
}
和实施:
struct AnimatableColorText: View {
let from: UIColor
let to: UIColor
let pct: CGFloat
let text: () -> Text
var body: some View {
let textView = text()
// This should be enough, but there is a bug, so we implement a workaround
// AnimatableColorTextModifier(from: from, to: to, pct: pct, text: textView)
// This is the workaround
return textView.foregroundColor(Color.clear)
.overlay(Color.clear.modifier(AnimatableColorTextModifier(from: from, to: to, pct: pct, text: textView)))
}
struct AnimatableColorTextModifier: AnimatableModifier {
let from: UIColor
let to: UIColor
var pct: CGFloat
let text: Text
var animatableData: CGFloat {
get { pct }
set { pct = newValue }
}
func body(content: Content) -> some View {
return text.foregroundColor(colorMixer(c1: from, c2: to, pct: pct))
}
// This is a very basic implementation of a color interpolation
// between two values.
func colorMixer(c1: UIColor, c2: UIColor, pct: CGFloat) -> Color {
guard let cc1 = c1.cgColor.components else { return Color(c1) }
guard let cc2 = c2.cgColor.components else { return Color(c1) }
let r = (cc1[0] + (cc2[0] - cc1[0]) * pct)
let g = (cc1[1] + (cc2[1] - cc1[1]) * pct)
let b = (cc1[2] + (cc2[2] - cc1[2]) * pct)
return Color(red: Double(r), green: Double(g), blue: Double(b))
}
}
}
有一个更简单的方法,借用 Apple 的 "Animating Views and Transitions" 教程代码。 HikeGraph 中 GraphCapsule 的实例化说明了这一点。
虽然 foregroundColor
无法设置动画,但 colorMultiply
可以。将前景色设置为白色,然后使用 colorMultiply 设置所需的实际颜色。从红色到蓝色的动画:
struct AnimateDemo: View {
@State private var color = Color.red
var body: some View {
Text("Animate Me!")
.foregroundColor(Color.white)
.colorMultiply(self.color)
.onTapGesture {
withAnimation(.easeInOut(duration: 1)) {
self.color = Color.blue
}
}
}
}
struct AnimateDemo_Previews: PreviewProvider {
static var previews: some View {
AnimateDemo()
}
}
我一直在尝试为 UI 的各个部分设置动画,但似乎您无法为 SwiftUI 文本的前景色设置动画?我想在状态改变时平滑地切换一些文本的颜色。如果我为文本周围视图的背景颜色设置动画效果很好,但前景色不起作用。有没有人幸运地为这样的变化设置动画?不确定这是 Xcode 测试版错误还是它的预期功能...
Text(highlightedText)
.foregroundColor(color.wrappedValue)
.animation(.easeInOut)
// Error: Cannot convert value of type 'Text' to closure result type '_'
Text
的颜色 属性 在 SwiftUI
或 UIKit
中不可设置动画。 但你可以达到你需要的结果:
struct ContentView: View {
@State var highlighted = false
var body: some View {
VStack {
ZStack {
// Highlighted State
Text("Text To Change Color")
.foregroundColor(.red)
.opacity(highlighted ? 1 : 0)
// Normal State
Text("Text To Change Color")
.foregroundColor(.blue)
.opacity(highlighted ? 0 : 1)
}
Button("Change") {
withAnimation(.easeIn) {
self.highlighted.toggle()
}
}
}
}
}
您可以将此功能封装在自定义 View
中并在您喜欢的任何地方使用它。
SwiftUI 中有一个很好的协议,可让您为任何内容设置动画。即使是不可动画的东西! (例如文字颜色)。该协议称为 AnimatableModifier。
如果您想了解更多信息,我写了一篇完整的文章来解释它是如何工作的:https://swiftui-lab.com/swiftui-animations-part3/
下面是一个关于如何实现这种视图的示例:
AnimatableColorText(from: UIColor.systemRed, to: UIColor.systemGreen, pct: flag ? 1 : 0) {
Text("Hello World").font(.largeTitle)
}.onTapGesture {
withAnimation(.easeInOut(duration: 2.0)) {
self.flag.toggle()
}
}
和实施:
struct AnimatableColorText: View {
let from: UIColor
let to: UIColor
let pct: CGFloat
let text: () -> Text
var body: some View {
let textView = text()
// This should be enough, but there is a bug, so we implement a workaround
// AnimatableColorTextModifier(from: from, to: to, pct: pct, text: textView)
// This is the workaround
return textView.foregroundColor(Color.clear)
.overlay(Color.clear.modifier(AnimatableColorTextModifier(from: from, to: to, pct: pct, text: textView)))
}
struct AnimatableColorTextModifier: AnimatableModifier {
let from: UIColor
let to: UIColor
var pct: CGFloat
let text: Text
var animatableData: CGFloat {
get { pct }
set { pct = newValue }
}
func body(content: Content) -> some View {
return text.foregroundColor(colorMixer(c1: from, c2: to, pct: pct))
}
// This is a very basic implementation of a color interpolation
// between two values.
func colorMixer(c1: UIColor, c2: UIColor, pct: CGFloat) -> Color {
guard let cc1 = c1.cgColor.components else { return Color(c1) }
guard let cc2 = c2.cgColor.components else { return Color(c1) }
let r = (cc1[0] + (cc2[0] - cc1[0]) * pct)
let g = (cc1[1] + (cc2[1] - cc1[1]) * pct)
let b = (cc1[2] + (cc2[2] - cc1[2]) * pct)
return Color(red: Double(r), green: Double(g), blue: Double(b))
}
}
}
有一个更简单的方法,借用 Apple 的 "Animating Views and Transitions" 教程代码。 HikeGraph 中 GraphCapsule 的实例化说明了这一点。
虽然 foregroundColor
无法设置动画,但 colorMultiply
可以。将前景色设置为白色,然后使用 colorMultiply 设置所需的实际颜色。从红色到蓝色的动画:
struct AnimateDemo: View {
@State private var color = Color.red
var body: some View {
Text("Animate Me!")
.foregroundColor(Color.white)
.colorMultiply(self.color)
.onTapGesture {
withAnimation(.easeInOut(duration: 1)) {
self.color = Color.blue
}
}
}
}
struct AnimateDemo_Previews: PreviewProvider {
static var previews: some View {
AnimateDemo()
}
}