SwiftUI endless gradient background - xcode

I want to make a scrolling app with a gradient background. As user scrolls - background color changes.
For example, the bottom is black and the top is white I would specify the height of a VStack for 8000, and for this height, as the user scrolls the screen he will see the color change.
I didn't find any solution. Tried making LinearGradient for VStack and Rectangle figures for its full height, but it only covers the phone screen size (can't fill all 8000 height points). So if I scroll upwards, the gradient is lost and it only displays the black screen.
Thank you]1

You can achieve this using a rectangle within a ZStack:
struct ContentView: View {
var body: some View {
ScrollView {
ZStack(alignment: .top) {
// Example width and height. Width should be the width of the device
Rectangle().frame(width: 10000, height: 2000).foregroundColor(.clear).background(LinearGradient(gradient: Gradient(colors: [.white, .black]), startPoint: .top, endPoint: .bottom))
// Add your actual content here:
Text("Yeet")
}
}
}
}

Related

Simple (but complex) layout design with SwiftUI

I'm trying to code a simple layout design with SwiftUI without success!
Here's what I'd like to do:
ScrollView {
VStrack {
// Header with an orange background.
// This orange color should also apply to the status bar.
}
VStrack {
// Content with a white background.
// This white color should always go to the bottom.
}
}
I first tried to apply an orange background to the first VStack and a white background to the second VStack but I couldn't color the status bar in orange even with .ignoresSafeArea().
Then I tried to apply an orange background to the ScrollView and a white background again to the second VStack but I couldn't color the bottom of the screen in white even with .infinity.
I also tried to use LazyVStack but nothing happened.
Do you guys have any idea to make this works? :-)
You can try setting the height of the content to be at least the screen height:
.frame(minHeight: UIScreen.screenHeight)
Here's the sample code of the full view's body (you can replace the HStacks with VStacks, as long as you fill the width):
ScrollView {
HStack {
Spacer()
Text("Header")
Spacer()
}
.padding()
.background(.orange)
HStack {
Spacer()
Text("Content")
Spacer()
}
.padding()
.frame(minHeight: UIScreen.screenHeight, alignment: .top)
.background(.white)
}
.background(Color.orange.ignoresSafeArea(.all, edges: .top))

SwiftUI - showing an image in a List/Form without a border around the cell

I'm trying to create a List or Form in SwiftUI to display a few fields. One of them is an image. I'd like it to show without any borders in the cell but the content of the row seems to contain some sort of inherent margin inside the cell that I can't get rid of.
This is my code at the moment...
List {
Section("Photo") {
Button {
// do a thing
} label: {
Image(uiImage: image)
.resizable()
.aspectRatio(1, contentMode: .fit)
}
}
.listRowBackground(Color.gray)
TextField("Name", text: viewStore.binding(\.$name))
DatePicker("DOB", selection: viewStore.binding(\.$dob), displayedComponents: [.date])
}
And this is what it looks like...
Really there are two problems here.
How do I get rid of the grey border so that the image fills to the extent of the cell?
How do I resize the image with what in UIKit would be scaleAspectFill? It is currently squeezing the image to fit.
OK... I had some ideas while typing out the question.
I've solved this (at least partly) by providing the listRowInsets on the Section.
Section {
// the content
}
.listRowInsets(.init(top: 0, leading: 0, bottom: 0, trailing: 0))
This then displays like...
Now to work on fixing the aspect ratio. 🤣
I fixed the aspect ratio using this answer...
How to center crop an image in SwiftUI

In SwiftUI, how to scale content inside scrollView with dynamic changing scrolling area?

I'm developing MacOS App with SwiftUI.
Let's say we have a fixed size window, which will show a scrollable image.
Now I want to create a feature which can let user to scale the image, and can scroll and view the scaled image inside the window.
The problem is, once I scaled up the image, the scroll area seems not expended together, and the scroll area is not big enough to reach each corner of the image.
struct ContentView: View {
var body: some View {
ScrollView([.horizontal, .vertical] , showsIndicators: true ){
Image("test")
.scaleEffect(2)
}
.frame(width: 500, height: 500)
}
}
I have tried to set the Image's frame by using GeometryReader, but got the same result.
MacOS 11.1, Xcode 12.3
Thanks!
.scaleEffect seems to perform a visual transform on the view without actually affecting its frame, so the ScrollView doesn't know to accommodate the bigger size.
.resizable() and .frame on the image seem to do the trick:
struct ContentView: View {
#State private var scale : CGFloat = 1.0
var body: some View {
VStack {
ScrollView([.horizontal, .vertical] , showsIndicators: true ){
Image(systemName: "plus.circle")
.resizable()
.frame(width: 300 * scale,height: 300 * scale)
}
.frame(width: 500, height: 500)
Slider(value: $scale, in: (0...5))
}
}
}

SwiftUI ScaleEffect image with center of mousepointer

I like to scale an image on macOS with a pinch - gesture, which works well.
But the image is scaled always (and expectingly) centers.
What I need is that an Image is scaled with an anchor on the mousepointer. But I have no clue how to read the current mousePointer position.
What I have so far is:
GeometryReader { geo in
ScrollView([.horizontal, .vertical], showsIndicators: true) {
Image(nsImage: image!)
.resizable()
.scaledToFill()
.animation(.default)
**// Here the 'anchor' should have a pointer position **
.scaleEffect(setZoom(magnificationLevel: magnificationState.scale), anchor: UnitPoint.center)
.frame(width: geo.size.width, height: geo.size.height)
.onAppear() {
self.imageMagnificationState = CGFloat(1.0)
}
}
}
Is there any snippet for this every day task? How to get the cursor position? SwiftUI doc is very lame here.

SwiftUI: How to clip just the bottom of an image

I have an image which I wish to pin to the top of the view with a height of 200. I started with the following:
struct ContentView: View {
var body: some View {
VStack {
Image("frog")
.resizable()
.scaledToFill()
.frame(height:200)
Spacer()
}
}
}
which gives me:
You can see the frame (with height 200) outlined in blue. Now, I want the image to continue to spill out of the safe zone to fill the top of the view, as it is doing. But I want clip the image at its bottom frame, so I get something like this:
I'd also be fine with something like this, where the whole image is shifted upwards to where the natural bottom of the image is at the bottom of the frame:
I've tried a wide array of modifiers, as well as using GeometryReader but have not been able to achieve either result. I need this to work for images of arbitrary dimensions.
To shift the image upwards you can do the following:
.frame(height:200, alignment: .bottom)
Here is alternate that gives you effect of your 2nd screenshot:
Image("frog")
.resizable()
.scaledToFill()
.frame(height:200)
.mask(Rectangle().edgesIgnoringSafeArea(.top)) // << here !!

Resources