4

I have my code as follows:

Rectangle()
    .fill(Color.red)
    .frame(width: 60, height: 60, alignment: .center)
    .cornerRadius(recording ? 5 : 30)

So I was wondering if .frame could be conditional just like .cornerRadius is. I am doing that in order to morph the shape, however I also need to make it smaller when it morphs. An example is a Voice Memos app's record button.

EV3REST
  • 105
  • 8

4 Answers4

10

If you're talking about using no frame modifier altogether (or providing a clean way to do different frames), a ViewModifier might be a good option:

struct ContentView: View {
    @State private var recording = false
    
    var body: some View {
        Rectangle()
            .fill(Color.red)
            .modifier(CustomFrameModifier(active: recording))
            .cornerRadius(recording ? 5 : 30)
    }
}

struct CustomFrameModifier : ViewModifier {
    var active : Bool
    
    @ViewBuilder func body(content: Content) -> some View {
        if active {
            content.frame(width: 60, height: 60, alignment: .center)
        } else {
            content
        }
    }
}
jnpdx
  • 45,847
  • 6
  • 64
  • 94
  • Oh, well. This is actually a lot cleaner. Thank you so much! – EV3REST Apr 01 '21 at 19:04
  • Such a clever and creative solution! I think this is the best approach because it gives you the flexibility of having no dimension to pass too. Can easily be extended to take parameters for the ternary expression so it can have one of three states essentially: value a, b and nil. – Barrrdi Mar 04 '22 at 11:13
4

Yes, you can use the ternary conditional statement with .frame as well.

Example:

.frame(width: recording ? 40 : 60, height: recording ? 40 : 60, alignment: .center)

0

I assume you wanted something like this

enter image description here

        Rectangle()
            .fill(Color.red)
            .frame(width: recording ? 45 : 60, height: recording ? 30 : 60, alignment: .center)
            .cornerRadius(recording ? 5 : 30)
            .onTapGesture {
                recording.toggle()
            }
            .animation(.default, value: recording)
Asperi
  • 228,894
  • 20
  • 464
  • 690
0

You can do with ?


enter image description here

import SwiftUI

struct ContentView: View {
    
    @State private var recording: Bool = Bool()
    @State private var color: Color = Color.blue
    
    var body: some View {
        
        ZStack {
            
            Circle()
                .fill(Color.white)
                .frame(width: 60.0, height: 60.0, alignment: .center)
                .shadow(radius: 10.0)
            
            Circle()
                .fill(color)
                .frame(width: recording ? 30.0 : 60.0, height: recording ? 30.0 : 60.0, alignment: .center)  // <<: Here!

 
        }
        .onTapGesture { recording.toggle() }
        .animation(.easeInOut, value: recording)
        .onChange(of: recording) { newValue in if newValue { colorFunction() } else { color = Color.blue } }

    }
    
    
    func colorFunction() {

        if (color != Color.red) { color = Color.red } else { color = Color.clear }
        
        DispatchQueue.main.asyncAfter(deadline: .now() + .seconds(1)) { if recording { colorFunction() } }
        
    }
    
}
ios coder
  • 1
  • 4
  • 31
  • 91