swiftswiftui

Why doesn't opacity work with a sheet view?


I've prepared some sample code for a problem where I can't achieve a flash effect (changing opacity from 1 to 0 and back) in a sheet view. This issue is also visible on the screen. Does anyone know why this happens and how to achieve the same effect as the flashButton in SwiftUI?

import SwiftUI

struct ContentView: View {
    
    @State var shouldFlashScreen = false
    @State var openSheet = false

    var body: some View {
        VStack {
            sheetButton
                .frame(width: 100, height: 100)
            
            flashButton
                .frame(width: 100, height: 100)
        }
    }
    
    @ViewBuilder
    var sheetButton: some View {
        Button {
            openSheet = true
        } label: {
            Text("Open sheet")
        }
        .sheet(isPresented: $openSheet) {
            flashButton
        }
    }
    
    @ViewBuilder
    var flashButton: some View {
        ZStack {
            Button {
                shouldFlashScreen = true
                withAnimation(.linear(duration: 0.05)) {
                    shouldFlashScreen = false
                }
            } label: {
                Text("Tap to flash")
            }
        }
        .frame(maxWidth: .infinity, maxHeight: .infinity)
        .background(.gray)
        .opacity(shouldFlashScreen ? 0 : 1)
        .border(.red)
    }
    
}

#Preview {
    ContentView()
}

Video: enter image description here


Solution

  • Try changing the way you are applying the opacity change and use a completion callback for the animation:

    Button {
        withAnimation(.linear(duration: 0.05)) {
            shouldFlashScreen = true
        } completion: {
            shouldFlashScreen = false
        }
    } label: {
        Text("Tap to flash")
    }
    

    Animation