8

I'm currently trying to handle SwiftUI by following a tutorial, but somehow I can't solve one issue:

I created another View, namely my HomeView.swift - this file contains the following code:

import SwiftUI

struct Home: View {
    var menu = menuData
    @State var show = false

    var body: some View {
        ZStack {

            ZStack(alignment: .topLeading) {
                Button(action: { self.show.toggle() }) {
                    HStack {
                        Spacer()
                        Image(systemName: "list.dash")
                            .foregroundColor(Color("primary"))
                    }
                    .padding(.trailing, 20)
                    .frame(width: 90, height: 60)
                    .background(Color.white)
                    .cornerRadius(30)
                    .shadow(color: Color("shadow"), radius: 10, x: 0, y: 10)
                }
                Spacer()
            }

            ZStack(alignment: .topTrailing) {
                Button(action: { self.show.toggle() }) {
                    HStack {
                        Spacer()
                        Image(systemName: "map.fill")
                            .foregroundColor(Color("primary"))
                    }
                    .padding(.trailing, 20)
                    .frame(width: 44, height: 44)
                    .background(Color.white)
                    .cornerRadius(30)
                    .shadow(color: Color("shadow"), radius: 10, x: 0, y: 10)
                }
                Spacer()
            }

            MenuView(show: $show)
        }
    }
}

struct Home_Previews: PreviewProvider {
    static var previews: some View {
        Home()
    }
}

struct MenuRow: View {
    var text: String?
    var image: String?
    var body: some View {
        HStack {
            Image(systemName: image ?? "")
                .foregroundColor(Color("third"))
                .frame(width: 32, height: 32, alignment: .trailing)
            Text(text ?? "")
                .font(Font.custom("Helvetica Now Display Bold", size: 15))
                .foregroundColor(Color("primary"))
            Spacer()
        }
    }
}

struct Menu: Identifiable {
    var id = UUID()
    var title: String
    var icon: String
}

let menuData = [
    Menu(title: "My Account", icon: "person.crop.circle.fill"),
    Menu(title: "Reservations", icon: "house.fill"),
    Menu(title: "Sign Out", icon: "arrow.uturn.down")
]


struct MenuView: View {
    var menu = menuData
    @Binding var show: Bool

    var body: some View {
        VStack(alignment: .leading, spacing: 20) {
            ForEach(menu) { item in
                MenuRow(text: item.title, image: item.icon)
            }
            Spacer()
        }
        .padding(.top, 20)
        .padding(30)
        .frame(minWidth: 0, maxWidth: .infinity)
        .background(Color.white)
        .cornerRadius(30)
        .padding(.trailing, 60)
        .shadow(radius: 20)
        .rotation3DEffect(Angle(degrees: show ? 0 : 60), axis: (x: 0, y: 10, z: 0))
        .animation(.default)
        .offset(x: show ? 0 : -UIScreen.main.bounds.width)
        .onTapGesture {
            self.show.toggle()
        }
    }
}

As you can see, right in the beginning, inside of my Home struct, I tried to align two ZStacks - one .topLeading and one .topTrailing. Reading the docs, this should change its position, but somehow it doesn't. Both stack stay centered.

BTW I haven't particularly touched ContenView.swift yet.

1
  • 2
    Container's alignment parameter affects content views of the container not container itself. This is the good article about alignments Alignment Guides in SwiftUI Commented Nov 15, 2019 at 3:31

2 Answers 2

7

Actually, for either inner ZStack, you need to set frames. This can make them reach edges.

  ZStack{

            ZStack{
            Button(action: { self.show.toggle() }) {
                HStack {
                    Spacer()
                    Image(systemName: "list.dash")
                        .foregroundColor(Color("primary"))
                }
                .padding(.trailing, 20)
                .frame(width: 90, height: 60)
                .background(Color.white)
                .cornerRadius(30)
                .shadow(color: Color("shadow"), radius: 10, x: 0, y: 10)
            }
            Spacer()
            }.frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .topLeading)

        ZStack{
            Button(action: { self.show.toggle() }) {
                HStack {
                    Spacer()
                    Image(systemName: "map.fill")
                        .foregroundColor(Color("primary"))
                }
                .padding(.trailing, 20)
                .frame(width: 44, height: 44)
                .background(Color.white)
                .cornerRadius(30)
                .shadow(color: Color("shadow"), radius: 10, x: 0, y: 10)
            }
            Spacer()
        }.frame(maxWidth: .infinity, maxHeight: .infinity,  alignment: .topTrailing)

        MenuView(show: $show)
        }
Sign up to request clarification or add additional context in comments.

4 Comments

How do you know that we need to set the frames for Z stack because what's wrong with what @Tim has done ?
If you don't set frame for ZStack, those views have no superView with specific dimensions. The dimension of those are are as same as the ZStack itself.
Oh btw, this doesnt work currently so adding spacers with hstack and vstack should do it
It's still working. I just show how to use the frame of ZStack to change a position from the center. if just adding width, it's off the center horizontally. Now I update with both dimension, you can see both buttons now are at upper corners separately.
4
struct Home: View {
var menu = menuData
@State var show = false

var body: some View {
    ZStack {
        VStack {
            HStack {
                Button(action: { self.show.toggle() }) {
                    HStack {
                        Spacer()
                        Image(systemName: "list.dash")
                            .foregroundColor(Color("primary"))
                    }
                    .padding(.trailing, 20)
                    .frame(width: 90, height: 60)
                    .background(Color.white)
                    .cornerRadius(30)
                    .shadow(color: Color("shadow"), radius: 10, x: 0, y: 10)
                }
                Spacer()

                Button(action: { self.show.toggle() }) {
                    HStack {
                        Spacer()
                        Image(systemName: "map.fill")
                            .foregroundColor(Color("primary"))
                    }
                    .padding(.trailing, 20)
                    .frame(width: 44, height: 44)
                    .background(Color.white)
                    .cornerRadius(30)
                    .shadow(color: Color("shadow"), radius: 10, x: 0, y: 10)
                }
            }
            Spacer()
        }
        MenuView(show: $show)
    }
}

}

Is this the layout that you are looking for? With VStack and HStack you can align the views to the top and on both edges

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.