Home > Blockchain >  How to prevent certain items in VStack from being clipped?
How to prevent certain items in VStack from being clipped?

Time:08-05

If I have a VStack with limited height and the contents of the VStack require more height than what's available, is there a way I can control which items get clipped?

I created the short sample below to illustrate.

I'd like "Bottom" to be clipped instead of the black rectangle when the toggle is set to "Open".

I've tried .fixedSize, .layoutPriority and a number of other things.

enter image description here

enter image description here

import SwiftUI

struct ContentView: View {
    @State var isOpen: Bool = false
    
    var body: some View {
        container
    }
    
    @ViewBuilder var container: some View {
        VStack {
            header
            content
        }
        .frame(width: 300, height: 110)
        .background(.gray)
        .cornerRadius(20)
    }
    
    @ViewBuilder var header: some View {
        RoundedRectangle(cornerRadius: 5)
            .frame(width: 50, height: 10)
    }
    
    @ViewBuilder var content: some View {
        VStack(alignment: .leading) {
            Picker("mypicker", selection: $isOpen) {
                Text("Open").tag(true)
                Text("Closed").tag(false)
            }
            .pickerStyle(.segmented)
            if isOpen {
                Text("Top")
                Text("Middle")
                Text("Bottom")
            }
        }
    }
}

CodePudding user response:

Try with .opacity instead, so that your VStack saves spaces in advance without messing up your layouts later. Code is below the image:

enter image description here

enter image description here

struct ContentView: View {
@State var isOpen: Bool = false

var body: some View {
    container
}
@ViewBuilder var container: some View {
    VStack {
        header
        content
    }
    .frame(width: 300, height: 110)
    .background(.gray)
    .cornerRadius(20)
}

@ViewBuilder var header: some View {
    RoundedRectangle(cornerRadius: 5)
        .frame(width: 50, height: 10)
        .padding(.top)
}
@ViewBuilder var content: some View {
    VStack(alignment: .leading) {
        Picker("mypicker", selection: $isOpen) {
            Text("Open").tag(true)
            Text("Closed").tag(false)
        }
        .pickerStyle(.segmented)
        Group {
            Text("Top")
            Text("Middle")
            Text("Bottom")
        }
        .opacity(isOpen ? 1 : 0) //here
    }
  }
}

CodePudding user response:

In this case I would separate layout of header and content (assuming requirement that header should be visible always) independently of what's really in header or content

It can be done using free space consumer (like Color) and overlay

@ViewBuilder var container: some View {
    VStack {
        header
        Color.clear
            .overlay(content)   // << here !!
    }
    .frame(width: 300, height: 110, alignment: .top)
    .background(.gray)
    .cornerRadius(20)
}

demo

Tested with Xcode 13.4 / iOS 15.5

CodePudding user response:

Well, when my container's size is smaller than its content, I will think about using a ScrollView. It guarantees user can see everything.

@ViewBuilder var container: some View {
    ScrollView {
        VStack {
            header
            content
        }.pading()
    }
    .frame(width: 300, height: 110)
    .background(.gray)
    .cornerRadius(20)
}

enter image description here

enter image description here

enter image description here

  • Related