ARTICLE AD BOX
I’m building a reusable custom bottom sheet component in SwiftUI because my app supports iOS 15, so I can’t use .sheet with detents yet. Functionally everything works the sheet opens and closes but I’m running into a visual glitch:
Problem
When the bottom sheet animates in or out, I see a brief flicker or fade of the underlying content beneath the sheet. It looks like the previous frame of the view is fading through before the animation finalizes. This only lasts a fraction of a second but is very noticeable.
Can someone help me take a look at whats happening? The code I provided should be easy enough to copy and paste into a barebone project:
import SwiftUI enum BottomSheetType: CaseIterable { case boxImage case normal } struct ContentView: View { @StateObject private var viewModel = BottomSheetViewModel() var body: some View { ZStack { Text("Show Bottom Sheet") .padding() .background(Capsule().stroke()) .onTapGesture(perform: viewModel.toggle) if viewModel.isPresented { ZStack(alignment: .bottom) { VStack { Spacer() // The part that's going to be reusable VStack(spacing: 0) { switch viewModel.type { case .boxImage: ListModal(viewModel: viewModel) case .normal: NormalModal() case .none: EmptyView() } } .padding(.bottom, 30) .frame(maxWidth: .infinity) .background(Color(.systemGray6)) .cornerRadius(20) } } .transition(.move(edge: .bottom)) .scaleEffect(1) } } .ignoresSafeArea() } } struct ListModal: View { var viewModel: BottomSheetViewModel var body: some View { ForEach(viewModel.items.indices, id: \.self) { index in let genre = viewModel.items[index] Text(genre) .font(.title2) .frame(height: 30) } } } struct NormalModal: View { var body: some View { VStack(spacing: 20) { Text("Heading 1") .font(.largeTitle) .frame(height: 30) Text("Heading 2") .font(.title) .frame(height: 30) Text("Heading 3") .font(.title2) .frame(height: 30) } .padding(.top, 20) } } final class BottomSheetViewModel: ObservableObject { var type: BottomSheetType? @Published var isPresented: Bool = false var items: [String] = [] func generateRandomItems() { type = BottomSheetType.allCases.randomElement()! let count = Int.random(in: 5...10) items = (5...count).map { "Item \($0)" } } func toggle() { generateRandomItems() withAnimation(.spring()) { isPresented.toggle() } } }14.5k9 gold badges84 silver badges133 bronze badges
1771 gold badge2 silver badges11 bronze badges
Explore related questions
See similar questions with these tags.
