swiftui

FullScreenCover with dynamic frame size -possible?


I have a view in which I calculate the size of an image. These size should be the size for the fullscreencover sheet. The problem is, that the @State variable didn't change the value when I assign a new value.

I read something, and it could be that @State variable is not good for it. But what else I can do to reach my goal.

struct ExerciseDetailTopViewiPad: View {
    
    let exercise: ExerciseData
    
    @State private var showExerciseImageViewer = false
    @State private var maxWidth: CGFloat = 533
    @State private var maxHeight: CGFloat = 850
    
    var body: some View {
    
        Image(uiImage: exercise.exerciseImage.imageExerciseFromBase64)
            .onTapGesture {
                let dim: CGFloat = exercise.exerciseImage.imageExerciseFromBase64.size.height / exercise.exerciseImage.imageExerciseFromBase64.size.width
                let newWidth = maxHeight / dim - 30 // 30 height of top menu
                maxWidth = newWidth.rounded(.up) // ==> HERE IS THE PROBLEM - the assignment didn't change the variable value
                showExerciseImageViewer = true
            }
            .fullScreenCover(isPresented: $showExerciseImageViewer) {
                ExerciseDetailImageVieweriPad(exercise: exercise)
                    .frame(maxWidth: maxWidth, maxHeight: maxHeight)
                    .clipShape(RoundedRectangle(cornerRadius: 10))
                    .shadow(color: Color(white: 0.7), radius: 20)
                    .presentationBackground {Rectangle().fill(.clear)}
            }
    }
}

Solution

  • As I mentioned in my comment, use .fullscreencover(item: ...). It is designed for passing a data source for the sheet’s content.

    Alternatively, you can capture the variables (maxWidth, maxHeight) when you call fullScreenCover, as shown in the example code.

    This will present a fullScreenCover and inside it will display your ExerciseDetailImageVieweriPad view with the updated .frame(maxWidth: maxWidth, maxHeight: maxHeight)

     .fullScreenCover(isPresented: $showExerciseImageViewer) { [maxWidth, maxHeight] in
         ExerciseDetailImageVieweriPad(exercise: exercise)
             .frame(maxWidth: maxWidth, maxHeight: maxHeight)
             .clipShape(RoundedRectangle(cornerRadius: 10))
             .shadow(color: Color(white: 0.7), radius: 20)
             .presentationBackground {Rectangle().fill(.clear)}
     }
    

    If your question is about resizing the fullScreenCover itself, then just use .sheet with .presentationDetents([.height(maxHeight)]), such as:

    .sheet(isPresented: $showExerciseImageViewer) { [maxWidth, maxHeight] in
                ExerciseDetailImageVieweriPad(exercise: exercise)
                    .frame(maxWidth: maxWidth, maxHeight: maxHeight)
                    .clipShape(RoundedRectangle(cornerRadius: 10))
                    .shadow(color: Color(white: 0.7), radius: 20)
                    .presentationBackground {Rectangle().fill(.clear)}
                    .presentationDetents([.height(maxHeight)])
    }