Skip to content

Commit c95fb3c

Browse files
committed
Fix banner flickering when navigation to next screen
1 parent b12e323 commit c95fb3c

File tree

2 files changed

+82
-7
lines changed

2 files changed

+82
-7
lines changed

Sources/SwiftUIInfiniteCarousel/InfiniteCarousel.swift

Lines changed: 27 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ public struct InfiniteCarousel<Content: View, T: Any>: View {
1515
@State private var timer: Timer.TimerPublisher
1616
@State private var cancellable: Cancellable?
1717
@State private var selectedTab: Int = 1
18+
@State private var isScaleEnabled: Bool = true
1819
private let data: [T]
1920
private let seconds: Double
2021
private let content: (T) -> Content
@@ -61,7 +62,7 @@ public struct InfiniteCarousel<Content: View, T: Any>: View {
6162
.frame(maxWidth: .infinity, maxHeight: .infinity)
6263
.rotation3DEffect(transition == .rotation3D ? getRotation(positionMinX) : .degrees(0), axis: (x: 0, y: 1, z: 0))
6364
.opacity(transition == .opacity ? getValue(positionMinX) : 1)
64-
.scaleEffect(transition == .scale ? getValue(positionMinX) : 1)
65+
.scaleEffect(isScaleEnabled && transition == .scale ? getValue(positionMinX) : 1)
6566
.padding(.horizontal, horizontalPadding)
6667
.onChange(of: positionMinX) { offset in
6768
// If the user change the position of a banner, the offset is different of 0, so we stop the timer
@@ -105,6 +106,10 @@ public struct InfiniteCarousel<Content: View, T: Any>: View {
105106
}
106107
.onAppear {
107108
startTimer()
109+
isScaleEnabled = true
110+
}
111+
.onWillDisappear {
112+
isScaleEnabled = false
108113
}
109114
.onReceive(timer) { _ in
110115
withAnimation {
@@ -160,13 +165,28 @@ public enum TransitionType {
160165
case rotation3D, scale, opacity
161166
}
162167

168+
struct TestView: View {
169+
@State private var isActive: Bool = false
170+
var body: some View {
171+
NavigationView {
172+
VStack {
173+
InfiniteCarousel(data: ["Element 1", "Element 2", "Element 3", "Element 4"]) { element in
174+
Text(element)
175+
.font(.title.bold())
176+
.padding()
177+
.background(Color.green)
178+
}
179+
NavigationLink(destination: Text("Next screen"), isActive: $isActive) {
180+
Button("Go to next screen") {
181+
isActive = true
182+
}
183+
}
184+
}
185+
}
186+
}
187+
}
163188
struct InfiniteCarousel_Previews: PreviewProvider {
164189
static var previews: some View {
165-
InfiniteCarousel(data: ["Element 1", "Element 2", "Element 3", "Element 4"]) { element in
166-
Text(element)
167-
.font(.title.bold())
168-
.padding()
169-
.background(Color.green)
170-
}
190+
TestView()
171191
}
172192
}
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
//
2+
// File.swift
3+
//
4+
//
5+
// Created by Daniel Carvajal on 22-10-22.
6+
//
7+
8+
import Foundation
9+
import SwiftUI
10+
11+
// Monitors the life cycles of view (onWillAppear or onWillDisappear)
12+
private struct ViewLifeCycleHandler: UIViewControllerRepresentable {
13+
14+
let onWillDisappear: () -> Void
15+
let onWillAppear: () -> Void
16+
17+
func makeUIViewController(context: Context) -> UIViewController {
18+
ViewLifeCycleViewController(onWillDisappear: onWillDisappear, onWillAppear: onWillAppear)
19+
}
20+
21+
func updateUIViewController(_ uiViewController: UIViewController, context: Context) {}
22+
}
23+
24+
private class ViewLifeCycleViewController: UIViewController {
25+
let onWillDisappear: () -> Void
26+
let onWillAppear: () -> Void
27+
28+
init(onWillDisappear: @escaping () -> Void, onWillAppear: @escaping () -> Void) {
29+
self.onWillDisappear = onWillDisappear
30+
self.onWillAppear = onWillAppear
31+
super.init(nibName: nil, bundle: nil)
32+
}
33+
34+
required init?(coder: NSCoder) {
35+
fatalError("init(coder:) has not been implemented")
36+
}
37+
38+
override func viewWillDisappear(_ animated: Bool) {
39+
super.viewWillDisappear(animated)
40+
onWillDisappear()
41+
}
42+
override func viewWillAppear(_ animated: Bool) {
43+
super.viewWillAppear(animated)
44+
onWillAppear()
45+
}
46+
}
47+
48+
extension View {
49+
func onWillDisappear(_ perform: @escaping () -> Void) -> some View {
50+
background(ViewLifeCycleHandler(onWillDisappear: perform, onWillAppear: {}))
51+
}
52+
func onWillAppear(_ perform: @escaping () -> Void) -> some View {
53+
background(ViewLifeCycleHandler(onWillDisappear: {}, onWillAppear: perform))
54+
}
55+
}

0 commit comments

Comments
 (0)