2

I would like to add subviews to my VStack from bottom to top manner. By default VStack fills from Center only. I tried by giving Y Offset to subview but that doesn't generate output as expected.

Please find my code sample as below:

import SwiftUI
let colors = [Color.red, Color.green, Color.blue, Color.yellow]

struct DiskView: View {
    
    let id:Int!
    var body: some View {
        ZStack{
            colors[id]
            Text("\(id)").foregroundColor(.white)
        }
    }
}

struct TowerView: View {

    func hanoiTapped(){
        
    }
    
    var body: some View {
        ZStack{
            Image("hanoi_pillaar").gesture(TapGesture().onEnded({ _ in
                hanoiTapped()
            }))
            VStack() {
                DiskView(id:2).frame(width:50, height:10)
                DiskView(id:1).frame(width:50, height:10)
                }
            }
    }
}

struct ContentView: View {
    var body: some View {
        VStack {
            Text("Hello, world!")
            HStack{
                TowerView().padding()
            }
        }.padding()
    }
}

I used logic of 180 degree roatation as suggeste at How to fill SwiftUI's VStack from bottom to top with items, but it doesn't address my issue. It mirrors items of list.

Current Output Current Output Expected Output Expected Output

HarshIT
  • 4,583
  • 2
  • 30
  • 60

1 Answers1

0

I do not understand why you want something like this. As suggested, it seems like the only real way to fill bottom to top is to rotate the view, but in your example, you can easily do that by reordering the ids with a descending order and just pushing VStack to bottom using a spacer like this.

VStack() {
    Spacer()
    DiskView(id:1).frame(width:50, height:10)
    DiskView(id:2).frame(width:50, height:10)
}

or you can assign a frame to both tower Image and to your disk VStack, then you can set alignment to bottom in your VStack.

In addition, as you want to place them like disks you have to add bottom padding as well.

The result looks like this:

Result

The code:


import SwiftUI

let colors = [Color.red, Color.green, Color.blue, Color.yellow, Color.gray, Color.purple, Color.teal, Color.cyan]

struct DiskView: View {
    
    let id:Int!
    var body: some View {
        ZStack{
            colors[id % (colors.count - 1)]
            Text("\(id + 1)").foregroundColor(.white)
        }
    }
}

struct TowerView: View {
    
    func hanoiTapped(){
        
    }
    @State private var id = 0
    var body: some View {
        VStack {
            ZStack{
                Image("hanoi_pillaar"
                )
                .resizable()
                .frame(width: 300, height: 300)
                .gesture(TapGesture().onEnded({ _ in
                    hanoiTapped()
                }))
                VStack(spacing: 7) {
                    ForEach(0..<id, id: \.self) { index in
                        DiskView(id: index)
                            .frame(width: 150, height: 10)
                    }
                    .animation(.linear, value: id)
                }
                .padding(.bottom, 55)
                .frame(width: 300, height: 300, alignment: .bottom)
            }
            Button("Add Disks")
            {
                self.id += 1
            }
            .font(.title3)
            .padding(10)
            .frame(width: 110)
            .foregroundColor(.white)
            .background(.orange)
            .cornerRadius(7)
        }
    }
}

struct ContentView: View {
    var body: some View {
        HStack{
            TowerView().padding()
        }
    }
}

Also keep in mind that arrays start at 0, not 1, so you are skipping the first element of the color array by ordering id's starting from 1

grandsirr
  • 584
  • 4
  • 19
  • Thanks for responding. I have added my screenshots for better reference. – HarshIT Oct 19 '22 at 02:27
  • 1
    Spacer().frame(height:30) , works when I have 2 Disks. If there are more disks than 2, I may need to change the Spacer's height. Is there anyway to get VStack's height so I can make Spacer's height dynamic ? – HarshIT Oct 19 '22 at 02:32
  • I added a new solution, you can check it. – grandsirr Oct 19 '22 at 09:34