SwiftUI HStack slider does not appear - ios

I want to make a horizontal stack of images.
Unfortunately I am not able to slide to see full images.
struct ContentView: View {
var body: some View {
NavigationView {
List {
ScrollView {
VStack{
Text("Images").font(.title)
HStack {
Image("hike")
Image("hike")
Image("hike")
Image("hike")
}
}
}.frame(height: 200)
}
}
}
}

There are a couple of issues with your view.
You have got a List around your content - it causes problems because a list scrolls vertically, while I assume you want your images to scroll horizontally.
Next thing is that you probably don't want your title to scroll with the images - it needs to go outside the scroll view.
Last but not least, you need to make the images resizable and set their aspect ratio so that they are scaled down to fit the allocated space.
Try this:
struct ContentView: View {
var body: some View {
NavigationView {
VStack{
Text("Images").font(.title)
ScrollView(.horizontal) {
HStack {
Image("hike")
.resizable()
.aspectRatio(contentMode: .fit)
Image("hike")
.resizable()
.aspectRatio(contentMode: .fit)
Image("hike")
.resizable()
.aspectRatio(contentMode: .fit)
Image("hike")
.resizable()
.aspectRatio(contentMode: .fit)
} .frame(height: 200)
Spacer()
}
}
}
}
}

Related

SwiftUI TabView and ScrollView gesture conflict

I have a TabView which I made vertical by rotating, and a ScrollView inside it.
VTabView code sample here.
My ContentView is something like this:
struct ContentView: View {
// Omitted properties
var body: some View {
GeometryReader { geo in
VTabView(selection: $page) {
FirstPageView()
.frame(width: geo.size.width, height: geo.size.height)
.tag(0)
SecondPageView()
.frame(width: geo.size.width, height: geo.size.height)
.tag(1)
}
.tabViewStyle(PageTabViewStyle(indexDisplayMode: .never))
}
}
}
And in my SecondPageView:
struct SecondPageView: View {
// Omitted properties
var body: some View {
GeometryReader { geo in
VStack(alignment: .center, spacing: 30) {
Image(systemName: "chevron.compact.down")
.resizable()
.scaledToFit()
.frame(height: 50)
.foregroundColor(.white.opacity(0.5))
ScrollView {
// My ScrollView contents
}
}
.padding()
}
}
}
When I'm on the second page and trying to scroll back to the first page, I can do it only outside the ScrollView's bounds. If I scroll up in ScrollView's bounds, it would stuck when ScrollView reached the top.
So how can I make VTabView's scroll gesture work when ScrollView reached the top?

Constrain the size of an HStack (with Images) to the width of the device

I'm trying to make an iOS-app with SwiftUI.
Here's my code so far:
struct ContentView: View {
var body: some View {
VStack {
Spacer()
Text("SwiftUI Slots!")
Spacer()
HStack {
Text("Credits: 1025")
}
Spacer()
HStack {
Image("apple")
Image("cherry")
Image("star")
}
Spacer()
Button(action: {
print("Testing 124")
}, label: {
Text("Spin")
})
Spacer()
.scaledToFit()
}
}
}
The HStack with the three images in it causes trouble:
How can I constrain the size of the HStack to the size of the device, so that it doesn't overlap the edges?
Use resizable() and aspectRatio()modifier for Image.
HStack {
Image("apple").resizable().aspectRatio(contentMode: .fit)
Image("cherry").resizable().aspectRatio(contentMode: .fit)
Image("star").resizable().aspectRatio(contentMode: .fit)
}
You can also use
Image("star").resizable().scaledToFit()

How can I clip/mask HStack content to behave like a ScrollView where content is shown inside HStack?

I have a custom TabView (Snap Carousel) where I scroll content and snap to the TabView Content. The content is basically a HStack x times larger in width than the TabView where x is also the number of pages. I am getting the desired scroll behaviour but when I clip the MenuTabView, I lose the contents outside the visible area, on scrolling it is empty.
HStack(spacing : 0) {
Image("image1")
.aspectRatio(2.8, contentMode: .fit)
.frame(width: proxy.size.width)
Image("image2")
.aspectRatio(2.8, contentMode: .fit)
.frame(width: proxy.size.width)
}
.frame(maxWidth: proxy.size.width, alignment: .leading)
.clipped()
proxy is the GeometryProxy.
struct MenuTabView<Content: View> : View {
var body: some View {
GeometryReader { proxy in
ZStack {
content()
.offset(x: (CGFloat(index) * -proxy.size.width) + self.offset)
.gesture(
DragGesture()
........
}
}
}
The second Image is the second page, when I clip using .clipped() it scrolls but its not visible. How can I create a behaviour similar to ScrollView
Try to move lines
.frame(maxWidth: proxy.size.width, alignment: .leading)
.clipped()
after the .offset operator

SwiftUI Content View random padding

I am currently creating a content view for my application and am experiencing some strange behavior with padding. As seen in the photo below, there is quite a bit of space below the navigation bar at the top of the phone. I don't specify any padding here so I'm wondering why there is so much space between the top and where the image is displayed. The image doesn't have that large of a white box around it either.
My code does not specify any kind of margin or padding. I'm new to Swift and SwiftUI so I'm curious if there is some automatic padding applied to navigation views?
import Kingfisher
struct BottleView: View {
let bottle: Bottle
var body: some View {
VStack {
KFImage(URL(string: bottle.image ?? "")!)
.resizable()
.frame(width: 128, height: 256)
VStack(alignment: .leading) {
HStack {
Text(bottle.name)
.font(.title)
Spacer()
Text("Price")
}
HStack {
Text(bottle.varietal ?? "")
Spacer()
Text("$\(bottle.price ?? "")")
}
.font(.subheadline)
.foregroundColor(.secondary)
VStack(alignment: .leading) {
Text("Information")
.font(.title2)
Text(bottle.information ?? "")
}
}
}
}
}
If you apply a .background(Color.red) to the VStack, you'll see that it's centered in the screen.
var body: some View {
VStack {
Image("TestImage")
.resizable()
.frame(width: 128, height: 256)
/// ... more code
}
.background(Color.red)
}
This is because, by default, most SwiftUI views are centered. For example, try just a Text:
struct ContentView: View {
var body: some View {
Text("Hello, I'm centered!")
}
}
So if you don't want it centered, this is where Spacers come in. These expand to fill all available space, pushing all other views. Here's the code that gets rid of the "bit of space below the navigation bar at the top of the phone":
(note that I replaced your Bottle properties with static text, make sure you change them back)
struct BottleView: View {
// let bottle: Bottle
var body: some View {
VStack {
Image("TestImage")
.resizable()
.frame(width: 128, height: 256)
VStack(alignment: .leading) {
HStack {
Text("Blantons")
.font(.title)
Spacer()
Text("Price")
}
HStack {
Text("Bourbon")
Spacer()
Text("$59.99")
}
.font(.subheadline)
.foregroundColor(.secondary)
VStack(alignment: .leading) {
Text("Information")
.font(.title2)
Text("Product info here")
}
}
Spacer() /// spacer right here! pushes the other views up
}
.background(Color.red)
.navigationBarTitleDisplayMode(.inline) /// get rid of the additional top gap that the default Large Title navigation bar produces
}
}
Result:

GeometryReader in SwiftUI ScrollView causes weird behaviour and random offset

Im trying to create a ScrollView that in turn contains a GeometryReader (Explicitly not the other way around). The GeometryReader should contain an (image) with a fixed width and height. However when doing this, the ScrollView pushes the view "above" the screen, it seems like it's applying some random vertical offset.
var body: some View {
ScrollView {
GeometryReader { geometry in
Image("hp")
.resizable()
.aspectRatio(contentMode: .fill)
.frame(width: geometry.size.width, height: 400)
.clipped()
}
}
}
When removing the GeometryReader and just inserting the image it works fine.
Can somebody help?
Edit: Found a solution. I achieved the desired behaviour by telling the image that it should be as high and wide as the inner geometry reader. Then i'm setting the inner geometry reader
var body: some View {
GeometryReader { outerGeometry in
ScrollView {
VStack {
GeometryReader { innerGeometry in
Image("hp")
.resizable()
.aspectRatio(contentMode: .fill)
.frame(width: innerGeometry.size.width,
height: innerGeometry.size.height)
.offset(y: innerGeometry.frame(in: .global).minY/7)
.clipped()
}
.frame(width: outerGeometry.size.width, height: 300)
}
}
}
}
Just try to put ScrollView inside GeometryReader and not vice versa:
// ...
var body: some View {
GeometryReader { geometry in
ScrollView {
Image("hp")
.resizable()
.aspectRatio(contentMode: .fill)
.frame(width: geometry.size.width, height: 400)
.clipped()
}
}
}
// ...
and the result should be:
GeometryReader, if placed as you did, provides the size not of ScrollView itself, but of "Content View" in which image is placed. "Content View" of ScrollView is bigger than screen size, to allow spring effect at the edges, when one scrolls more than a scrolling document size.
The correct usage is in #Александр_Грабовский's answer.

Resources