SwiftUI анимирует все, кроме .foregroundColor
Исходя из стоимости @State var
, как я могу анимировать любые другие параметры, кроме одного? Например, я хочу оживить.offset
но не .foregroundColor
. Это может показаться легкой задачей, но это не так просто при использовании одного и того же "базового представления" для создания каких-то видов ячеек и комбинации различных модификаторов и переходов.
Для следующей анимации я пытаюсь "избежать" этой анимации с изменением цвета, допуская при этом смещение - мне нужно, чтобы изменение цвета происходило мгновенно, без анимации.
В этой анимации я также пытаюсь "избежать" анимации смены цвета. Проблема здесь в том, что в базовом представлении также есть переход.
Название "базового представления" LogoView
. Вот мой код:
struct Test_ForegroundColorAnimation: View {
var array: [Color] = [.yellow, .green, .blue]
@State var activeIndex1: Int = -1
@State var activeIndex2: Int = -1
@State var show: Bool = true
private func animationFor(index: Int) -> Animation {
Animation
.easeInOut(duration: 0.85)
.delay(0.15 * Double(array.count - index))
}
func zindexfor(index: Int) -> Double {
Double(index == activeIndex1 ? 100 : index)
}
func opacityfor(index: Int) -> Double {
self.activeIndex1 >= 0 ? (index == self.activeIndex1 ? 1 : 0) : 1
}
var body: some View {
VStack(alignment: .leading, spacing: 25) {
Spacer()
VStack {
Text("Offset animation").font(.title)
Text("Click any item").font(.subheadline)
}
ZStack {
ForEach(array.indices, id: \.self) { index in
LogoView(isSelected: index == self.activeIndex1, color: self.array[index])
.offset(x: self.activeIndex1 == -1 ? CGFloat(90 * index) : 0)
.zIndex(self.zindexfor(index: index))
.opacity(self.opacityfor(index: index))
.animation(self.animationFor(index: index))
.onTapGesture {
self.activeIndex1 = index == self.activeIndex1 ? -1 : index
}
}
}
.padding(.bottom, 70)
VStack {
Text("Transition").font(.title)
Text("Click any item").font(.subheadline)
}
Button(action: {
self.show.toggle()
}) {
Color.purple
.frame(width: 100, height: 70)
.overlay(Text("Activate transition!").foregroundColor(.white))
}
HStack(spacing: 5) {
ForEach(array.indices, id: \.self) { index in
HStack {
if self.show {
LogoView(isSelected: index == self.activeIndex2, color: self.array[index])
.transition(AnyTransition.move(edge: .bottom))
.onTapGesture {
self.activeIndex2 = index == self.activeIndex2 ? -1 : index
}
}
}
.frame(width: 90, height: 90)
.animation(self.animationFor(index: index))
}
}
}
}
}
struct Test_ForegroundColorAnimation_Previews: PreviewProvider {
static var previews: some View {
Test_ForegroundColorAnimation()
}
}
struct LogoView: View {
var isSelected: Bool = false
var color: Color = Color(#colorLiteral(red: 0.8078431487, green: 0.02745098062, blue: 0.3333333433, alpha: 1))
var shadow: Color = Color(#colorLiteral(red: 0.4392156899, green: 0.01176470611, blue: 0.1921568662, alpha: 1))
var body: some View {
Image(systemName: "heart.fill")
.resizable()
.frame(width: 28, height: 28)
.foregroundColor(isSelected ? Color(#colorLiteral(red: 1, green: 1, blue: 1, alpha: 1)) : color)
.padding()
.overlay(
Circle()
.stroke(lineWidth: 3)
.foregroundColor(color)
)
.background(
Circle()
.foregroundColor(isSelected ? color : Color(#colorLiteral(red: 1, green: 1, blue: 1, alpha: 1)))
.shadow(color: isSelected ? color.opacity(0.7) : Color(#colorLiteral(red: 0, green: 0, blue: 0, alpha: 1)).opacity(0.3), radius: 5, x: 0, y: 10)
)
.frame(width: 90, height: 90)
}
}
1 ответ
Если я правильно понял, что вам нужно, вот исправление
struct LogoView: View {
var isSelected: Bool = false
var color: Color = Color(#colorLiteral(red: 0.8078431487, green: 0.02745098062, blue: 0.3333333433, alpha: 1))
var shadow: Color = Color(#colorLiteral(red: 0.4392156899, green: 0.01176470611, blue: 0.1921568662, alpha: 1))
var body: some View {
Image(systemName: "heart.fill")
.resizable()
.frame(width: 28, height: 28)
.foregroundColor(isSelected ? Color(#colorLiteral(red: 1, green: 1, blue: 1, alpha: 1)) : color)
.padding()
.overlay(
Circle()
.stroke(lineWidth: 3)
.foregroundColor(color)
)
.background(
Circle()
.foregroundColor(isSelected ? color : Color(#colorLiteral(red: 1, green: 1, blue: 1, alpha: 1)))
.animation(nil) // << fix !!
.shadow(color: isSelected ? color.opacity(0.7) : Color(#colorLiteral(red: 0, green: 0, blue: 0, alpha: 1)).opacity(0.3), radius: 5, x: 0, y: 10)
)
.frame(width: 90, height: 90)
}
}