Home > other >  SwiftUI change transition color
SwiftUI change transition color

Time:10-10

I think this is the third question I've asked while trying to achieve a certain effect in SwiftUI. Basically, I'm trying to animate a menu that slides up from the bottom of the screen after a button is clicked. There are a few technicalities to this effect:

  1. The "sliding up" part needs to be animated and any subviews inside the view that slides up shouldn't render mid-animation, resulting in a choppy experience. See this question Choppy Animation SwiftUI Nested Views

  2. The "sliding up" view needs to be a white rounded rectangle. (It will have text subviews)

  3. To add contrast, the view that previously occupied the screen needs to be darkened when the sliding up view slides up. This also needs to be animated.

Here is some sample code that achieves 1) but fails at 2) and 3). It fails at 2) because the sliding up view is for some reason bracketed by whitespace, so the white rounded rectangle doesn't have the contrast of the darkened other view. It fails at 3) because I haven't found a way to animate changes in color.

Sample code:

struct ContentView: View {
    @State var show: Bool = Bool()
    
    var body: some View {
        VStack {
            Button(action: { show.toggle() }, label: { show ? Text("hide") : Text("show") })
                .animation(nil)
            Spacer()
            Other(show: show)
                .brightness(show ? -0.1: 0)
                
            Spacer()
            Group {
                if show { CollapsibleView().transition(.move(edge: .bottom)) }
            }
            .opacity(show ? 1.0 : 0.0)
        }

        .animation(.linear(duration: 0.2))
    }
}
struct Other: View {
    var show: Bool
    var body: some View {
        ZStack {
            Color.white
                .brightness(show ? -0.1: 0)
        }
    }
}
struct CollapsibleView: View {
    var body: some View {
        RoundedRectangle(cornerRadius: 40)
            .frame(height: 100)
            .foregroundColor(.blue)
    }
}

Note that the rounded rectangle is blue here to show the contrast between the random whitespace.

CodePudding user response:

You can try use offset instead transition for better animation:

struct ContentView: View {
    
    @State private var show: Bool = Bool()

    var body: some View {
        
        VStack {
            
            Button(action: { show.toggle() }, label: { show ? Text("hide") : Text("show") })

            Spacer()
            
            CollapsibleView(show: show)

        }
        
    }
}

struct CollapsibleView: View {
    
    let show: Bool
    
    var body: some View {

        RoundedRectangle(cornerRadius: 40)
            .frame(height: 100)
            .foregroundColor(.blue)
            .padding(.horizontal)
            .offset(y: show ? .zero : 200.0)
            .animation(.default, value: show)
 
    }
}
  • Related