[英]SwiftUI animation not working when embedded inside another view
我做了一個可重復使用的圓形進度條。 我應用repeatForever
animation 來保持它的旋轉,但它僅在直接與 @State 或 @Published 變量一起使用時有效,並且在嵌入另一個視圖時無效。
可重復使用的環視圖。 哪個是圓形進度條
struct RingView: View {
private let percent: CGFloat = 80 // Keeping it fixed 80 for test purpose
var color = Color.primaryLightColor // Some random color
@Binding var show: Bool
var body: some View {
ZStack {
GeometryReader { bounds in
Circle()
.trim(from: self.show ? self.progress : 1, to: 1)
.stroke(
LinearGradient(gradient: Gradient(colors: [self.color]), startPoint: .topTrailing, endPoint: .bottomLeading),
style: StrokeStyle(lineWidth: self.lineWidth(width: bounds.size.width), lineCap: .round, lineJoin: .round, miterLimit: .infinity, dash: [20, 0], dashPhase: 0)
)
.rotationEffect(Angle(degrees: 90))
.animation(.none)
.frame(width: bounds.size.width, height: bounds.size.height)
}
}
.rotationEffect(.degrees(show ? 360.0 : 0.0))
.animation(show ? Animation.linear(duration: 1.0).repeatForever(autoreverses: false) : .none)
}
func multiplier(width: CGFloat) -> CGFloat {
width / 44
}
func lineWidth(width: CGFloat) -> CGFloat {
5 * self.multiplier(width: width)
}
var progress: CGFloat {
1 - (percent / 100)
}
}
進度按鈕。 它使用上面的 RingView。 一般用例是在執行長后台任務時顯示 animation。
RingView animation 在此 ProgressButton 中不起作用
struct ProgressButton: View {
var action: () -> Void
var image: Image? = nil
var text: String = ""
var backgroundColor: Color = Color.blue
var textColor: Color = .white
@Binding var showProgress: Bool
var body: some View {
Button(action: action) {
HStack {
if showProgress {
RingView(color: textColor, show: self.$showProgress)
.frame(width: 25, height: 25)
.transition(.scale)
.animation(.Spring())
} else {
image?
.renderingMode(.original)
.resizable()
.frame(width: 25, height: 25)
}
Text(text)
.font(.headline)
.foregroundColor(textColor)
}
.padding()
.frame(minWidth: 0, maxWidth: .infinity, minHeight: 50, alignment: .center)
.background(backgroundColor)
.clipShape(RoundedRectangle(cornerRadius: 5, style: .continuous))
}.buttonStyle(PlainButtonStyle())
}
}
當 RingView animation 工作時。 當我直接使用它時,如下所示。
struct LoginView: View {
@State var showProgress = true
var body: some View {
VStack {
// WORKING
RingView(show: self.$showProgress)
.frame(width: 25, height: 25)
// NOT WORKING
ProgressButton(action: {
self.showProgress = true
}, image: Image("password-lock"), text: "Login", backgroundColor: .blue, showProgress: self.showProgress)
}
}
}
我想我在理解 @Binding 和 @State 的工作方式時犯了一些錯誤。
Animation 在 state更改時激活。 在提供的代碼中沒有任何變化,所以根本沒有 animation。
以下是主要更改,因此我使它起作用。 使用 Xcode 11.4 / iOS 13.4 進行測試(對缺少的自定義依賴項進行了一些復制)
1) 關閉初始 animation
struct LoginView: View {
@State var showProgress = false
// ... other code
// no model provided so used same state for progress
ProgressButton(action: {
self.showProgress.toggle() // << activate change !!!
}, image: Image("password-lock"), text: L.Login.LoginSecurely, backgroundColor: self.isLoginButtonEnabled ? Color.primaryLightColor : Color.gray, showProgress: $showProgress)
2)在進度按鈕內增加內環激活state; 同樣的 state 用於隱藏/取消隱藏和激活不起作用,再次,因為當環出現時沒有變化(已經是真的)所以環沒有被激活
@State private var actiavteRing = false // << here !!
var body: some View {
Button(action: action) {
HStack {
if showProgress {
RingView(color: textColor, show: self.$actiavteRing) // !!
.frame(width: 25, height: 25)
.transition(.opacity)
.animation(.spring())
.onAppear { self.actiavteRing = true } // <<
.onDisappear { self.actiavteRing = false } // <<
3) 在 Ring 中修復了 animation 停用以避免累積效應(.none 在這里不起作用),所以
.rotationEffect(.degrees(show ? 360.0 : 0.0))
.animation(show ? Animation.linear(duration:
1.0).repeatForever(autoreverses: false) : .default) // << here !!
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.