How to tap on a button under a Spacer SwiftUI - swiftui

I have a ZStack in which there are separate 2 VStacks. The First VStack has a Navlink, and a Second one has a ScrollView to enable scrolling over that button. Also Second VStack has a dynamic Spacer on top (that changes based on scrolling).
When I put VStack with a Navlink over VStack with a ScrollView, problem is seemed to be solved (Navlink work), but then on scroll they are visible and tapable on ScrollView.(button has to be under)
Problem:
How to tap on the Navlink if they are in the First VStack and the second one has a ScrollView on VStack with Navlink ?
My code:
#State var scroll:CGFloat = 350
ZStack{
VStack(spacing: 0){
ScrollView{
Spacer()
.frame(height: scroll )
VStack{
Text("123")
}
}
}.background(.black)
// second
VStack{
Spacer()
.frame(height: 200)
HStack{
NavigationLink(destination: TransferView()){
VStack (spacing: -10){
Image("transferBlack")
.resizable()
.frame(width:100, height: 100)
Text("Transfer")
.foregroundColor(.white)
}
}
}
Spacer()
}
}

Related

Swiftui vertical paging tabview with scrollview inside

My goal is to have a vertical paginated tabview with a scrollview inside. Scrolling as soon as you finish the scrollview you pass to the other tab and if the content of the scrollview has a lower height than the screen, scrolling passes directly to the next tab.
var body: some View {
GeometryReader { proxy in
TabView {
ForEach(colors, id: \.self) { color in
ScrollView(.horizontal, showsIndicators: false) {
HStack(alignment: .bottom, spacing: 20) {
ForEach(0..<15) { i in
//GeometryReader { block in
VStack(alignment: .leading) {
Text("Block test test test test test test \(i)")
}
.rotationEffect(.degrees(-90))
.frame(width: 70, height: proxy.size.width, alignment: .leading)
.background(Color.green)
.id(i)
//}
//.offset(y: proxy.size.width / 2)
}
}
.frame(height: proxy.size.height)
.background(Color.blue)
}
.frame(width: proxy.size.height, height: proxy.size.width)
.background(Color.pink)
}
.frame(width: proxy.size.width,height: proxy.size.height)
}
.frame( width: proxy.size.height, height: proxy.size.width)
.rotationEffect(.degrees(90), anchor: .topLeading)
.offset(x: proxy.size.width)
.tabViewStyle(
PageTabViewStyle(indexDisplayMode: .never)
)
}
}
These are the steps I followed:
created a tabview with horizontal scrolls inside
Rotated the tabview by 90°
Rotated the Vstacks inside the scrollview by -90°
The result is exact and the scrolling of the contents is continuous passing smoothly between scroll and tab, but the only problem is that I can't control the dimensions of the Vstacks inside the scrollview and therefore I can't have Vstacks with different heights in based on the content.
I tried to add a GeometryReader { block for the VStacks but besides not giving me the correct measurements of the VStacks it breaks the layout completely.
How can I get the dimensions of each Vstack correctly?

How to move vstack at top of the screen in swiftui?

how to move this stack top of the screen in swiftUI.
below my code there.
[1]: https://i.stack.imgur.com/wBD2c.png
You just need to add Spacer() & embed your view in VStack & HStack to force push the view to the top.
VStack {
VStack {
//Your VStack
}
Spacer()
}
You can remove the HStack and place the Spacer() within your VStack which will force the view to the top.
var body: some View {
VStack {
Text("Hello World")
Text("Test")
Spacer()
}
}
Or if you want to keep the View to the left of the screen you can use another VStack and Spacer()
var body: some View {
VStack {
HStack {
VStack {
Text("Hello World")
Text("Test")
Spacer()
}
Spacer()
}
}
}
If you are just getting started with SwiftUI I highly recommend Paul Hudson's 100 Days of SwiftUI. It's free and will teach you a lot about SwiftUI.

List rows not centered

I am displaying some rows in a list (actually, 2 parallel lists in the example posted here), from a custom row view labeled EventRow.
In order to avoid bad UI on larger devices like an iPad, I limited the width of the EventRow to 200.
How could I get the EventRows to be centered in my lists on larger devices ?
I tried applying a .center alignment to the EventRows in the ForEach methods of my lists, tried doing the same on the lists as well, but nothing seems to work.
As an alternate solution, is there a way to set a MAX Spacer width ? I know you can set a minLength, but not a MAX it seems...
Here's a screenshot on the iPad Pro 11 sim :
The code for my EventRow file is as follows :
import SwiftUI
struct EventRow: View {
var body: some View {
VStack{
HStack {
Text("Text one")
Spacer()
Text("Text two")
}
HStack {
Spacer()
Image(systemName: "flame")
.font(.body)
Spacer()
} // END of second HStack
.padding(.top, -14)
} //END of Vstack
.frame(maxWidth: 200) // To limit width on larger devices
.listRowBackground(LinearGradient(gradient: Gradient(colors: [Color.white, Color.blue]), startPoint: .top, endPoint: .bottom))
}
}
struct EventRow_Previews: PreviewProvider {
static var previews: some View {
EventRow().previewLayout(.fixed(width: 300, height: 60))
}
}
And my ContentView :
struct ContentView: View {
struct listsSetup: ViewModifier {
func body(content: Content) -> some View {
return content
.frame(maxHeight: UIScreen.main.bounds.size.height/3)
.overlay(RoundedRectangle(cornerRadius: 10).stroke(Color.blue, lineWidth: 1))
.padding([.top, .bottom])
}
}
#State private var selected : Int = 0
var body: some View {
VStack {
HStack {
VStack { // 1 list Vstack
VStack {
Text("List 1")
.padding(.top)
List {
EventRow()
EventRow()
} // END of 1st List
}
.modifier(listsSetup())
} // END of 1st list VStack
VStack { // 2nd Vstack
VStack {
Text("List 2")
.padding(.top)
List {
EventRow()
EventRow()
} // END of Landings List
}
.modifier(listsSetup())
} // End of 2nd List VStack
} // End of 1st & 2nd lists HStack
.padding(.top)
Spacer()
Picker("", selection: $selected){
Text("0").tag(0)
Text("1").tag(1)
}.pickerStyle(SegmentedPickerStyle())
Text("\(selected)")
} // END of VStack
} // END of body
}
Again, any help would be appreciated.
Just embed it in one more container, like below (tested with Xcode 11.4)
VStack {
VStack{
HStack {
Text("Text one")
Spacer()
Text("Text two")
}
HStack {
Spacer()
Image(systemName: "flame")
.font(.body)
Spacer()
} // END of second HStack
.padding(.top, -14)
} //END of Vstack
.frame(maxWidth: 200) // To limit width on larger devices
}.frame(maxWidth: .infinity) // << here !!

How position HStack in bottom of my screen no use the spacer()

I want move the HStack in bottom of my screen no use the spacer() because when use the spacer move the logo for top of my screen.
Here is a solution without using Spacer:
struct ContentView: View {
var body: some View {
VStack {
VStack {
Text("Image")
Text("Some text")
}.frame(minHeight: 0, maxHeight: .infinity)
HStack {
Text("Bottom")
}
}
}
}
I know you asked for no spacer, but this code shows you can use them without your logo going to the top of the screen. Alternatively you can use ".position(CGPoint(...))"
struct ContentView: View {
var body: some View {
VStack {
Spacer()
VStack (alignment: .center) {
Image("your-image").resizable().frame(width: 90, height: 95)
Text("TCheck time").font(.title).foregroundColor(.gray)
}.padding()
Spacer()
HStack (alignment: .bottom) {
Text("2020 SplitWay").font(.subheadline).foregroundColor(.gray)
}
}
}
}

Spacing Issue with SwiftUI

I am experiencing a weird spacing behavior that I'm hoping someone can explain. I have two views, the main view (ContentView) contains a child view called PlayerToolbar. The desired behavior is for ContentView take up the entire screen with PlayerToolbar being rendered at the very bottom of the screen. PlayerToolbar contains image buttons and spacers. The issue I am running into is ContentView only takes up a portion of the screen and PlayerToolbar is not aligned to the bottom as shown in the image.
Here is the code for ContentView
struct ContentView: View {
var body: some View {
VStack{
Spacer()
Text("Main Content")
Spacer()
PlayerToolBar()
}.background(Color.blue)
}
}
And here is the code for PlayerToolbar:
struct PlayerToolBar: View {
var body: some View {
HStack{
Spacer()
Button(action: {
print("backward button pressed")
}){
Image(systemName: "gobackward.10").renderingMode(.original) .resizable().aspectRatio(contentMode: .fit)
}
Spacer()
Button(action: {
print("play button pressed")
}){
Image(systemName: "play.circle").renderingMode(.original) .resizable().aspectRatio(contentMode: .fit)
}
Spacer()
Button(action: {
print("go forward button pressed")
}){
Image(systemName: "goforward.10").renderingMode(.original) .resizable().aspectRatio(contentMode: .fit)
}
Spacer()
Button(action: {
print("jot button pressed")
}){
Image(systemName: "pencil.circle").renderingMode(.original) .resizable().aspectRatio(contentMode: .fit)
}
Spacer()
}.background(Color(UIColor.secondarySystemBackground))
}
}
I have found that if add one Text object in my PlayerToolbar between the first Spacer and Button, the screen renders as I expect
...
Spacer()
Text(" ")
Button(action: {
print("backward button pressed")
}){
Image(systemName: "gobackward.10").renderingMode(.original) .resizable().aspectRatio(contentMode: .fit)
}
...
Any idea of why it is behaving the way it is and why a Text makes it act the way I prefer?
The problem, I think, is because your PlayerToolbar has no height and it is hard for the layout logic to determine one. Nothing in your PlayerToolbar has an explicit height. Your images are made resizable, but nothing in your views is telling how to resize them.
By adding a Text() view, your images now have some height to match, and so it works as you expect it.
Other solutions to break the ambiguity are (choose any, not all):
Set a frame height to the PlayerToolbar:
PlayerToolBar().frame(height: 40)
Set the height for at least one of your images:
Image(systemName: "gobackward.10")
.renderingMode(.original)
.resizable()
.frame(height: 40)
.aspectRatio(contentMode: .fit)
Set the height to one of your buttons:
Button(action: {
print("backward button pressed")
}){
Image(systemName: "gobackward.10")
.renderingMode(.original)
.resizable()
.aspectRatio(contentMode: .fit)
}.frame(height: 40)
Set the height of the HStack in your PlayerToolbar.
Remove the resizable() modifier in at least one of your images.
Image(systemName: "pencil.circle").renderingMode(.original).aspectRatio(contentMode: .fit)
All these alternatives aim at the same thing, making sure your images know how much to grow/shrink. There are of course many other options. These are just a few.