Why SwiftUI ScrollView not working properly? - ios

Everything in this view works fine except that my scrollview does not scroll to bottom and bounces back towards up.
This the screenshot below, I'm not able to add video of the view but I am sharing the code and screenshot of the view.
enter image description here
import SwiftUI
import AVKit
struct Servicer_rental_form7: View {
#State var isLinkActive = false
#State var shouldShowImagePicker = false
#State var avatarImage = UIImage(systemName: "photo.on.rectangle.angled")!
private let player = AVPlayer(url: URL(string: "YOUR-URL.mp4")!)
#State var isChecked:Bool = false
func toggle(){isChecked = !isChecked}
#State var isLinkActive1 = false
var body: some View {
ZStack{
ScrollView(.vertical, showsIndicators: false) {
VStack{
Text("Upload Images")
.offset(x:-getReact().width/3.5,y: getSafearea().bottom + 10)
.font(.system(size: 22,weight: .semibold,design: .default))
Button( action: {
shouldShowImagePicker = true
}, label: {
Image( systemName: "camera")
.foregroundColor(Color("YellowAccent"))
.offset(x:-getReact().width/10)
Text("Upload Image").underline()
.foregroundColor(Color.black)
.offset(x:-getReact().width/10)
.overlay(
RoundedRectangle(cornerRadius: 10)
.stroke(Color("YellowAccent"), lineWidth: 2)
.frame(width:380, height: 60)
.offset(x: getReact().width/40, y: getSafearea().bottom + -35)
)
})
.offset(x: -getReact().width/19, y: getSafearea().bottom + 50)
Image(uiImage: avatarImage)
.resizable()
.frame(width: 380, height:290)
.padding(.all)
.offset(y: getSafearea().bottom + -150)
.overlay(
RoundedRectangle(cornerRadius: 10)
.stroke(Color.gray, lineWidth: 3)
.frame(width: 380, height:300)
.offset(x: 5,y: getSafearea().bottom + -155)
)
.offset(x: 5,y: getSafearea().bottom + 180)
Text("Upload 3D Floor Plans")
.offset(x:-getReact().width/5.5,y: getSafearea().bottom + 50)
.font(.system(size: 22,weight: .semibold,design: .default))
Button( action: {
shouldShowImagePicker = true
}, label: {
Image( systemName: "camera")
.foregroundColor(Color("YellowAccent"))
.offset(x:-getReact().width/10)
Text("Upload Image").underline()
.foregroundColor(Color.black)
.offset(x:-getReact().width/10)
.overlay(
RoundedRectangle(cornerRadius: 10)
.stroke(Color("YellowAccent"), lineWidth: 2)
.frame(width:380, height: 60)
.offset(x: getReact().width/40, y: getSafearea().bottom + -35)
)
})
.offset(x: -getReact().width/19, y: getSafearea().bottom + 80)
Text("Upload Video")
.offset(x:-getReact().width/3.75,y: getSafearea().bottom + 110)
.font(.system(size: 22,weight: .semibold,design: .default))
Button( action: {
// shouldShowImagePicker = true
}, label: {
Image( systemName: "camera")
.foregroundColor(Color("YellowAccent"))
.offset(x:-getReact().width/10)
Text("Upload Video").underline()
.foregroundColor(Color.black)
.offset(x:-getReact().width/10)
.overlay(
RoundedRectangle(cornerRadius: 10)
.stroke(Color("YellowAccent"), lineWidth: 2)
.frame(width:380, height: 60)
.offset(x: getReact().width/40, y: getSafearea().bottom + -35)
)
})
.offset(x: -getReact().width/19, y: getSafearea().bottom + 140)
Group{
VideoPlayer(player: player)
.onAppear() {
player.play()
}
.frame(width: 350, height: 290)
.cornerRadius(20)
.offset( y: getSafearea().bottom + 165)
Button(action: toggle){
HStack{
Image(systemName: isChecked ? "checkmark.square.fill": "square")
.foregroundColor(.green)
Text("I agree to terms and conditions")
.foregroundColor(Color.black)
.font(.system(size: 15,weight: .medium, design: .default))
}
//.padding(.leading, 50)
}//button1
.offset( x:-40,y: getSafearea().bottom + 165)
Button(action: {
//code
}, label: {
HStack{
Image("flashLane 1")
Text("Flash Lane")
.bold()
}
.frame(width: 140, height: 40)
})
.buttonStyle(.borderedProminent)
.tint(.orange)
.offset(x: -getReact().width/4.5,y: getSafearea().bottom + 190)
Button(action: {
//code
}, label: {
HStack{
Image("REasyLane")
Text("R-Eazy Lane")
.bold()
}
.frame(width: 140, height: 40)
})
.buttonStyle(.borderedProminent)
.tint(.purple)
.offset(x: getReact().width/4.5,y: getSafearea().bottom + 130)
Button(action: {
//action
isLinkActive1 = true
}) {
Text("Publish")
.foregroundColor(Color.white)
.fontWeight(.bold)
.frame (width: 330, height: 20)
.padding()
.background(Color("YellowAccent"))
.cornerRadius(10)
.shadow(color: .gray, radius: 5, x: 0, y: 4)
}
.offset(x: 6,y: getSafearea().bottom + 140)
.padding(.bottom)
}//grp
} //vstack
.frame(width: getReact().width, height: getReact().height)
.sheet(isPresented: $shouldShowImagePicker, content: {
ImagePicker(avatarImage: $avatarImage) })
.padding(.top)
// .background(
// NavigationLink(destination: Servicer_rental_form2(), isActive: $isLinkActive) {
// EmptyView()
// }
// .hidden()
//)
}
//.frame(width: getReact().width)
}
// .padding(.top,-80)
.toolbar {
ToolbarItem(placement: .principal) {
Text("Filter")
.frame(width: 300, height: 10)
.foregroundColor(Color.black)
.font(.system(size: 30,weight: .medium, design: .default))
}
}
}
}
struct Servicer_rental_form7_Previews: PreviewProvider {
static var previews: some View {
Servicer_rental_form7()
}
}
Note: getReact() and getSafearea() are methods I have made separately for sizing of components and removing or adding them does not affect scrollview issue.

There is some issue with offset or getReact/getSafeArea.
I ran your code by removing offset, and it's working fine at my end.

Related

How to shape an Image into an circle

iam unsing a UiKit Image picker and trying to setup an Profil Pic for the User. Everything's works fine, the image gets displayed. But iam trying to make it into a Circle. I Tried using clipShape with an circle but it doesn't work. i followed the tutorial "My Images 1: Photo Picker and Camera in SwiftUI"
struct ProfileView: View {
#EnvironmentObject var appUser: User
#EnvironmentObject var appInfo: AppInformation
var body: some View {
ZStack {
Rectangle()
.frame(width: 400, height: 720)
.cornerRadius(50)
.foregroundColor(.gray)
.overlay(
HStack {
if let image = appUser.profilBild {
Image(uiImage: image)
.resizable()
.frame(width: 100, height: 100)
.scaledToFill()
.clipShape(RoundedRectangle(cornerRadius: 15))
.overlay(Circle().stroke(Color.orange, lineWidth: 10))
.onTapGesture {
appInfo.source = .library
appInfo.showPicker = true
}
.padding(20)
.shadow(radius: 10)
.overlay(
ZStack{
Rectangle()
.frame(width: 20, height: 20)
.offset(x: 35, y: -35)
.foregroundColor(.white)
Image(systemName: "plus.circle.fill")
.resizable()
.frame(width: 30, height: 30)
.offset(x: 35, y: -35)
.foregroundColor(.blue)
.shadow(radius: 10)
}
)
}
else {
Image(systemName: "person.circle")
.resizable()
.frame(width: 100, height: 100)
.onTapGesture {
appInfo.source = .library
appInfo.showPicker = true
}
.padding(20)
.shadow(radius: 10)
.overlay(
ZStack{
Rectangle()
.frame(width: 20, height: 20)
.offset(x: 35, y: -35)
.foregroundColor(.white)
Image(systemName: "plus.circle.fill")
.resizable()
.frame(width: 30, height: 30)
.offset(x: 35, y: -35)
.foregroundColor(.blue)
.shadow(radius: 10)
}
)
}
VStack {
Text(appUser.username)
.font(.largeTitle)
.frame(width: 240 ,alignment: .leading)
.offset(x: -10, y: -25)
.lineLimit(1)
Text(appUser.name)
.frame(width: 220, alignment: .leading)
.offset(x: -15,y: -20)
.lineLimit(1)
}
}
.frame(width: 400, height: 720, alignment: .topLeading)
)
.padding()
ZStack {
Rectangle()
.foregroundColor(.secondary)
.frame(width: 380, height: 510)
.cornerRadius(45)
}
.frame(width: 400, height: 700, alignment: .bottom)
.padding()
}
.sheet(isPresented: $appInfo.showPicker) {
ImagePicker(sourceType: appInfo.source == .library ? .photoLibrary : .camera, selectedImage: $appUser.profilBild)
}
.frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .top)
}
}
You were almost there :)
Your only mistake was the order you placed your modifiers. ORDER MATTERS!!
Place scaledToFill() and clipShape() before the frame modifier.
Like such:
.resizable()
.scaledToFill()
.clipShape(Circle())
.frame(width: size, height: size)

SwiftUI Crash BoxVTable

I am seeing an odd crash with some beta testers on TestFlight. It seems to be at app startup, but prior to the point where we are making any network calls. There does not seem to be a lot on the internet regarding this, and symbolication isn't helping much either. Just curious if anyone has run into this before and what they did about it? I have had it happen on two tester's devices and I have never been able to recreate the issue locally.
For a bit of context, I am creating a list view on my main screen with a LazyVGrid that contains a LazyHGrid inside of it that are both filled using published vars from my viewmodel, though this seems to happen prior to any of those being created.
Thanks for any ideas / help
Edit: Some more details / actual code:
The view with the grids:
import SwiftUI
import Kingfisher
struct FeaturedView: View {
#EnvironmentObject var viewRouter: ViewRouter
#EnvironmentObject var tabRouter : TabRouter
#StateObject var loadingViewModel = LoadingViewModel()
private let imageProcessor = SVGImgProcessor()
private let playerManager = PlayerManager.shared
private var gridItemLayout = [GridItem(.flexible())]
let userDefaults = UserDefaults.standard
var body: some View {
let padding: CGFloat = 20
let paddingHStack: CGFloat = 25
GeometryReader { geometry in
ZStack(alignment: .top){
Color(hex:"#00091C").edgesIgnoringSafeArea(.all)
VStack {
HStack {
HStack {
Text("Hello, \(loadingViewModel.name)")
.frame(alignment: .leading)
.multilineTextAlignment(.center)
.font(Font.custom("poppins-medium", size: 20))
.foregroundColor(Color(hex:"#667C95"))
.padding(.leading, 15)
.padding(.top, 15)
.padding(.bottom, 15)
Image("PremiumStar")
.resizable()
.frame(width: 15.0, height: 15.0)
.opacity(userDefaults.isSubscriber() ? 1 : 0)
}
Spacer()
Button(action: {
print("Settings Clicked")
viewRouter.currentPage = .settingsFlow
}) {
Image("Settings")
.resizable()
.frame(width: 22.0, height: 22.0)
.padding(15)
}
}
ScrollView(showsIndicators: false) {
VStack(spacing: 10) {
LazyVGrid(columns: gridItemLayout, spacing: 17) {
ForEach(loadingViewModel.getCategories()) { category in
Text(category.title)
.foregroundColor(.white)
.font(Font.custom("poppins-bold", size: 30))
ZStack {
KFImage(URL(string: (category.background?.svg!)!))
.resizable()
.setProcessor(imageProcessor)
.frame(width: geometry.size.width - padding, height: 175, alignment: .topLeading)
.aspectRatio(contentMode: .fill)
.clipped()
.cornerRadius(5)
ScrollView(.horizontal, showsIndicators: false) {
LazyHGrid(rows: gridItemLayout, spacing: 20){
ForEach(loadingViewModel.getSoundsForCategory(category: category.key)) { sound in
Button(action: {
playerManager.play(sound: sound)
}) {
VStack {
ZStack{
RoundedRectangle(cornerRadius: 5).frame(width: 90, height: 90)
.foregroundColor(Color.black)
.opacity(0.85)
ZStack(alignment:.bottomTrailing){
KFImage(URL(string: sound.icon.png!)!)
.resizable()
.renderingMode(.template)
.foregroundColor(.white)
.frame(width: 75, height: 75)
.aspectRatio(contentMode: .fill)
.clipped()
Image("LockIcon")
.frame(width: 12, height: 12, alignment: .bottomTrailing)
.aspectRatio(contentMode: .fill)
.clipped()
.hidden(loadingViewModel.isSubscriber || sound.tier != 2)
}
}
Text(sound.name)
.foregroundColor(.white)
.font(Font.custom("poppins-regular", size: 12))
.lineLimit(1)
.frame(minWidth: 0, idealWidth: 90, maxWidth: 100, alignment: .center)
}
}
}
}.padding(.horizontal)
}
.frame(width: geometry.size.width - paddingHStack, height: 175, alignment: .topLeading)
}
Button("Explore All"){
print("Explore All \(category.title) Tapped")
tabRouter.categoryKey = category.key
tabRouter.hasChanged = true
tabRouter.currentTab = 1
}
.font(Font.custom("poppins-bold", size: 15))
.foregroundColor(Color.white)
}
}.padding(.bottom, 120)
}
}
}
}
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
FeaturedView()
}
}
That is loaded by this tab view, which goes between two screens which share the same viewModel / load the same data
// MARK: Tab View
var body: some View {
ZStack{
TabView(selection: $selectedTab){
FeaturedView()
.environmentObject(tabRouter)
.tabItem{
Label("FEATURED", image: "Featured")
}.tag(0)
.overlay(
VStack {
if (showOverlay && !isExpanded){
playView
} else {
EmptyView()
}
}
)
SoundView()
.environmentObject(tabRouter)
.tabItem{
Label("SOUNDS", image: "Sounds")
}.tag(1)
.overlay(
VStack {
if (showOverlay && !isExpanded){
playView
} else {
EmptyView()
}
}
)
}
}
}

SwiftUI - Dismiss a popup and add a button to the current main view , when a button in the popup is clicked

I'm new to swiftUI.
I have a button, on its click I'm displaying a popup view. When close button in the popup is clicked it should dismiss the popupview and add a new button onto the main view. Any help is appreciated. Here's my code
struct SelectLocation: View {
#State private var showPopUp = false
#State private var passCode: String = ""
var body: some View {
ZStack{
VStack{
Button(action: {
withAnimation {
self.showPopUp = true
}
}, label: {
Text("Select Location")
.frame(minWidth: 0, maxWidth: 500)
.padding()
.background(Color.clear)
.foregroundColor(Color.black)
.font(.custom("Open Sans", size: 18))
.overlay(
RoundedRectangle(cornerRadius: 10)
.stroke(Color.gray, lineWidth: 2)
)
})
if(self.showPopUp){
popupPassCode()
}
}
}
}
func popupPassCode()-> some View {
VStack{
SecureField("Enter Code", text: $passCode)
.frame(width: 300, height: 50, alignment: .leading)
.cornerRadius(3.0)
.overlay(RoundedRectangle(cornerRadius: 3.0)
.stroke(Color.gray, lineWidth: 1)
)
.padding()
Button(action: {
withAnimation {
self.showPopUp = false
self.showsCorrectOrIncorrect = true
}
}, label: {
Text("Enter")
.frame(width: 150, height: 30)
.padding()
.background(Color.red)
.foregroundColor(Color.white)
.font(.custom("Open Sans", size: 28))
})
if showsCorrectOrIncorrect {
btnStart()
}
}
.padding()
.frame(width: 440, height: 300)
.background(Color.white)
.cornerRadius(20)
.shadow(radius: 20 )
}
func btnStart() -> some View {
VStack{
Button(action: {
}, label: {
Text("Start Order")
.frame(width: 150, height: 30)
.background(Color.red)
.foregroundColor(Color.white)
.font(.custom("Open Sans", size: 28))
})
}
}
}
When Enter button in the popup is clicked , it should add a new button to the bottom of the main view (means view that has "Select Location" button)
Use a struct instead of function for the start button and pop up and show them when showPopUp and showsCorrectOrIncorrect is true.
struct SelectLocation: View {
#State private var showPopUp = false
#State private var passCode: String = ""
#State var showsCorrectOrIncorrect = false
var body: some View {
ZStack{
VStack{
Button(action: {
withAnimation {
self.showPopUp = true
}
}, label: {
Text("Select Location")
.frame(minWidth: 0, maxWidth: 500)
.padding()
.background(Color.clear)
.foregroundColor(Color.black)
.font(.custom("Open Sans", size: 18))
.overlay(
RoundedRectangle(cornerRadius: 10)
.stroke(Color.gray, lineWidth: 2)
)
})
if showPopUp {
PopUpPassCode(passCode: $passCode, showPopUp: $showPopUp, showsCorrectOrIncorrect: $showsCorrectOrIncorrect)
}
if showsCorrectOrIncorrect {
StartButton()
}
}
}
}
}
struct PopUpPassCode: View {
#Binding var passCode: String
#Binding var showPopUp: Bool
#Binding var showsCorrectOrIncorrect: Bool
var body: some View {
VStack{
SecureField("Enter Code", text: $passCode)
.frame(width: 300, height: 50, alignment: .leading)
.cornerRadius(3.0)
.overlay(RoundedRectangle(cornerRadius: 3.0)
.stroke(Color.gray, lineWidth: 1)
)
.padding()
Button(action: {
withAnimation {
self.showPopUp = false
self.showsCorrectOrIncorrect = true
}
}, label: {
Text("Enter")
.frame(width: 150, height: 30)
.padding()
.background(Color.red)
.foregroundColor(Color.white)
.font(.custom("Open Sans", size: 28))
})
}
.padding()
.frame(width: 440, height: 300)
.background(Color.white)
.cornerRadius(20)
.shadow(radius: 20 )
}
}
struct StartButton: View {
var body: some View {
VStack{
Button(action: {
}, label: {
Text("Start Order")
.frame(width: 150, height: 30)
.background(Color.red)
.foregroundColor(Color.white)
.font(.custom("Open Sans", size: 28))
})
}
}
}

LazyHStack cuts off content when scrolling

I have a LazyHStack nested in a ScrollView for showing some data from an API, but everytime I scroll it, the content is being cut off like this:
Here is the full struct:
struct MovieDetailView: View {
#EnvironmentObject private var navStack: NavigationStack
#ObservedObject var viewModel: MovieDetailVM
init(viewModel: MovieDetailVM) {
self.viewModel = viewModel
//UIScrollView.appearance().bounces = false
}
var body: some View {
GeometryReader { geometry in
ZStack(alignment: .top) {
ScrollView(showsIndicators: false) {
VStack {
GeometryReader { (proxy: GeometryProxy) in
if proxy.frame(in: .global).minY <= 0 {
Image(uiImage: (UIImage(data: viewModel.backdropData) ?? UIImage(named: JWConfig.IMG_PLACEHOLDER_MOVIE_BACKDROP))!)
.resizable()
.aspectRatio(contentMode: .fill)
.frame(width: proxy.size.width, height: 330)
} else {
Image(uiImage: (UIImage(data: viewModel.backdropData) ?? UIImage(named: JWConfig.IMG_PLACEHOLDER_MOVIE_BACKDROP))!)
.resizable()
.aspectRatio(contentMode: .fill)
.offset(y: -proxy.frame(in: .global).minY)
.frame(width: proxy.size.width, height: 330 + proxy.frame(in: .global).minY)
}
}
VStack(alignment: .leading) {
FDDivider(height: 20)
HStack {
Image(uiImage: (UIImage(data: viewModel.posterData) ?? UIImage(named: JWConfig.IMG_PLACEHOLDER_MOVIE_POSTER))!)
.resizable()
.aspectRatio(contentMode: .fill)
.frame(width: 120, height: 180)
.cornerRadius(20)
.clipped()
VStack(alignment: .leading) {
Text(viewModel.title)
.font(Font.custom(JWConfig.FONT_ARIAL, size: 25).weight(.semibold))
.foregroundColor(.SAPPHIRE)
.padding([.top, .bottom], 12)
.lineLimit(3)
HStack {
ForEach(viewModel.genres.prefix(2), id: \.ID) { genre in
JWBorderPill(text: genre.name, textSize: 12, textColor: .SAPPHIRE, borderColor: .DANUBE)
}
}
}.padding([.leading], 10)
Spacer()
}.padding([.leading, .trailing], 20)
FDDivider(height: 20)
HStack(spacing: 50) {
VStack {
Text("Release Date")
.font(Font.custom(JWConfig.FONT_ARIAL, size: 15))
.foregroundColor(.gray)
.padding([.bottom], 1)
Text(viewModel.releaseDate)
.font(Font.custom(JWConfig.FONT_ARIAL, size: 18).weight(.semibold))
}
VStack() {
Text("Duration")
.font(Font.custom(JWConfig.FONT_ARIAL, size: 15))
.foregroundColor(.gray)
.padding([.bottom], 1)
Text("\(viewModel.runtime)")
.font(Font.custom(JWConfig.FONT_ARIAL, size: 18).weight(.semibold))
}
VStack() {
Text("Rating")
.font(Font.custom(JWConfig.FONT_ARIAL, size: 15))
.foregroundColor(.gray)
.padding([.bottom], 1)
Text("\(String(format: "%.1f", viewModel.voteAverage)) / 10")
.font(Font.custom(JWConfig.FONT_ARIAL, size: 18).weight(.semibold))
}
}.frame(width: geometry.size.width)
VStack(alignment: .leading) {
Text("Overview")
.font(Font.custom(JWConfig.FONT_ARIAL, size: 23).weight(.semibold))
.foregroundColor(.SAPPHIRE)
.padding([.top, .bottom], 8)
Text(viewModel.overview)
.font(Font.custom(JWConfig.FONT_ARIAL, size: 17))
.foregroundColor(.gray)
}.padding([.leading, .trailing], 24)
VStack(alignment: .leading) {
Text("Production Companies")
.font(Font.custom(JWConfig.FONT_ARIAL, size: 23).weight(.semibold))
.foregroundColor(.SAPPHIRE)
.padding([.top], 8)
ScrollView(.horizontal, showsIndicators: false) {
LazyHStack {
ForEach(viewModel.productionCompanies, id: \.ID) { company in
ProductionCompanyCell(viewModel: ProductionCompanyCellVM(company))
}
}
}
}.frame(height: 250)
.padding([.leading], 24)
FDDivider(height: 400)
}.frame(width: geometry.size.width)
.background(Color.white)
.cornerRadiusWithEachCorner(50, corners: [.topLeft, .topRight])
.offset(y: 180)
}
}
HStack {
JWBackButton()
Spacer()
}.padding(EdgeInsets(top: 50, leading: 25, bottom: 0, trailing: 0))
}
}.edgesIgnoringSafeArea(.all)
}
}
Is there something wrong with my code? Please let me know if you need the full body code, and I'm using Xcode 12.4 at the moment

SwiftUI won't align ZStacks

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.
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)
}
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

Resources