relativeSize isn't adjusting HStack dimensions - swiftui

When .relativeSize is called on HStack{}, the borders do not come closer. Indicative of dimensions not being adjusted.
I've already tried rearranging the sequence of method calls on HStack, such that .relativeSize is called before and after .frame and .border
struct ContentView : View {
var body: some View{
VStack(alignment: .center, spacing: 1){
//Top box holding a rectangle
HStack{
Text("Test")
}
.frame(width: 355, height: 99, alignment: .center)
.relativeSize(width: 0.95, height: 0.95)
.border(Color.blue, width: 2)
//Bottom box holding 3 recangles
HStack{
Text("Test")
}
.frame(width: 355, height: 47, alignment: .center)
.border(Color.red, width: 1)
}
.frame(width: 355, height: 148, alignment: .center)
.border(Color.black, width: 1)
//body paren
}
}

Simply add a Spacer() before and after the text, and remove the .frame() modifier. This way the HStack will expand laterally as much as 0.95 the size of the containing VStack. Is this what you want?
struct ContentView : View {
var body: some View{
VStack(alignment: .center, spacing: 1){
//Top box holding a rectangle
HStack{
Spacer()
Text("Test")
Spacer()
}
.relativeSize(width: 0.95, height: 0.95)
.border(Color.blue, width: 2)
//Bottom box holding 3 recangles
HStack{
Text("Test")
}
.frame(width: 355, height: 47, alignment: .center)
.border(Color.red, width: 1)
}
.frame(width: 355, height: 148, alignment: .center)
.border(Color.black, width: 1)
//body paren
}
}

Related

Moving Horizontal ScrollView up top SwiftUI

I am trying to move the images in Horizontal ScrollView up top. They are currently at the bottom. I have tried adding NavigationView, .padding(), Spacer(), Adding a ZStack as a parent to HStack, and HStack(alignment: .top). I have been stuck for 3 days.
Is it possible to have Horizontal ScrollView up top?
Here is the code:
import SwiftUI
struct ContentView: View {
var body: some View {
NavigationView {
ScrollView(.horizontal) {
HStack(spacing: 15) {
Group {
Image("OutdoorDining1")
.frame(width: 230, height: 148)
Image("EatVegan")
.frame(width: 230, height: 148)
Image("CityView")
.frame(width: 230, height: 148)
Image("LiveMusic")
.frame(width: 230, height: 148)
}
Group {
Image("Seafood")
.frame(width: 230, height: 148)
Image("Blackowned")
.frame(width: 230, height: 148)
Image("Hookah")
.frame(width: 230, height: 148)
Image("OpenTilLate")
.frame(width: 230, height: 148)
}
Group {
Image("CentralAmerica")
.frame(width: 230, height: 148)
Image("Asian")
.frame(width: 230, height: 148)
Image("Mediterranean")
.frame(width: 230, height: 148)
}
Group {
Image("Steakhouses")
.frame(width: 230, height: 148)
Image("Kosher")
.frame(width: 230, height: 148)
}
Hi Christina and welcome to SO! You can use ChrisR's suggestion VStack + Spacer() - it's works, but if you building more complex UI and want to add ScrollView(.vertical) and more views use next hierarchy
struct ContentView: View {
var body: some View {
ZStack(alignment: .top) {
NavigationView {
ScrollView(.vertical) {
VStack {
ScrollView(.horizontal) {
HStack(spacing: 15) {
Group {
Image("EatVegan")
.frame(width: 230, height: 148)
Image("CityView")
.frame(width: 230, height: 148)
}
Group {
Image("Seafood")
.frame(width: 230, height: 148)
Image("Blackowned")
.frame(width: 230, height: 148)
}
}
}
// add other views here
}
}
}
}
}
}

How to detect whether the scrollview was scrolled or not in SwiftUI?

I have a horizontal ScrollView and would like to provide a function that when the first element is not visible anymore an arrow should appear to signalize that there are some other elements.
I've tried the DragGesture() to read the translation.width but it seems to be buggy in combination with the ScrollView.
So I'm looking for a way to detect whether the ScrollView was scrolled and how far. Is there any way?
private let gridItems = [GridItem(.flexible())]
ScrollView(.horizontal, showsIndicators: false) {
HStack{
LazyHGrid(rows: gridItems){
ForEach(viewModel.imageOptions, id: \.self){ image in
ZStack {
Image(image)
.resizable()
.aspectRatio(contentMode: .fit)
.frame(width: 60, height: 60)
.background(Color.white)
.clipShape(Circle())
.background(
Circle()
.clipShape(Circle())
.shadow(color: Color.black.opacity(0.4), radius: 3, x: 5.0, y: 5.0)
)
.onTapGesture {
print("selected")
}
.padding(15)
Circle()
.strokeBorder(Color.orange, lineWidth: 5)
.frame(width: 70, height: 70)
}
}
}
}
}
}

VStack .leading alignment

I can't get rid of this "leading" padding inside one of my VStacks.
I set alignment to "leading" for its parent VStack but it still shows some spacing on the left (for the text and red rounded rectangle). They were supposed to be placed on the left next to the blue edge on screenshot.
Any ideas on why this padding appears there?
Here's the code:
import SwiftUI
struct RegisterView: View {
var body: some View {
VStack(spacing: 0) {
HStack(alignment: .top) {
Text("Register")
.font(.custom("NotoSans-Regular", size: 24))
.fontWeight(.bold)
.foregroundColor(Color.tertiaryTitleColor)
}
.frame(width: 299, height: 39)
.padding(.top, 78)
HStack(spacing: 13) {
BroviderButton(imageName: "googleLogo")
BroviderButton(imageName: "facebookLogo")
}
.padding(.top, 47)
VStack(alignment: .leading, spacing: 0) {
Text("Register with E-mail")
.font(.custom("NotoSans-Regular", size: 16))
RoundedRectangle(cornerRadius: 25)
.fill(Color.red)
.frame(width: 40, height: 20)
}
.frame(width: 279)
.padding(.top, 61)
Spacer()
}
.frame(maxHeight: /*#START_MENU_TOKEN#*/.infinity/*#END_MENU_TOKEN#*/)
.frame(maxWidth: /*#START_MENU_TOKEN#*/.infinity/*#END_MENU_TOKEN#*/)
.background(Color.loginBackgroundColor)
.ignoresSafeArea()
}
}
struct RegisterView_Previews: PreviewProvider {
static var previews: some View {
RegisterView()
}
}
struct BroviderButton: View {
var imageName: String
var body: some View {
ZStack {
RoundedRectangle(cornerRadius: 27.5)
.frame(width: 133, height: 56, alignment: /*#START_MENU_TOKEN#*/.center/*#END_MENU_TOKEN#*/)
.shadow(color: Color.dropShadowColor, radius: 1, x: 10, y: 20)
.offset(y: 15)
.opacity(0.2)
.blur(radius: 20)
.opacity(0.2)
VStack {
VStack {
Image(imageName)
.resizable()
.scaledToFit()
}
.frame(height: 28, alignment: /*#START_MENU_TOKEN#*/.center/*#END_MENU_TOKEN#*/)
}
.frame(width: 133, height: 56, alignment: /*#START_MENU_TOKEN#*/.center/*#END_MENU_TOKEN#*/)
.foregroundColor(/*#START_MENU_TOKEN#*/.blue/*#END_MENU_TOKEN#*/)
.background(Color.loginBackgroundColor)
.cornerRadius(27.5)
.opacity(1)
}
}
}
You need also apply alignment to frame of container, like
VStack(alignment: .leading, spacing: 0) {
Text("Register with E-mail")
.font(.custom("NotoSans-Regular", size: 16))
RoundedRectangle(cornerRadius: 25)
.fill(Color.red)
.frame(width: 40, height: 20)
}
.frame(width: 279) // << do you really need this? why?
.frame(maxWidth: .infinity, alignment: .leading) // << here !!
.padding(.top, 61)

Implementing Box-Shadow in SwiftUI

I'm trying to implement the following css code in SwiftUI
background: #FFFFFF;
box-shadow: 0px 10px 20px rgba(223, 227, 240, 0.2);
border-radius: 27.5px;
It should look like this (barely visible shadow below the button):
Here's the code i'm currently experimenting with:
import SwiftUI
struct RegisterView: View {
var body: some View {
VStack(spacing: 0) {
HStack(alignment: .top) {
Text("Register")
.font(.custom("NotoSans-Regular", size: 24))
.fontWeight(.bold)
.foregroundColor(Color.tertiaryTitleColor)
}
.frame(width: 299, height: 39)
.padding(.top, 78)
HStack {
BroviderButton(imageName: "googleLogo")
BroviderButton(imageName: "facebookLogo")
}
.padding(.top, 47)
Spacer()
}
.frame(maxHeight: .infinity)
.frame(maxWidth: .infinity)
.background(Color.loginBackgroundColor)
.ignoresSafeArea()
}
}
struct RegisterView_Previews: PreviewProvider {
static var previews: some View {
RegisterView()
}
}
struct BroviderButton: View {
var imageName: String
var body: some View {
ZStack {
RoundedRectangle(cornerRadius: 27.5)
.stroke(Color.dropShadowColor,lineWidth: 1)
.frame(width: 133, height: 56, alignment: .center)
.shadow(color: .black, radius: 2, x: 1, y: 2)
VStack {
VStack {
Image(imageName)
.resizable()
.scaledToFit()
}
.frame(height: 28, alignment: .center)
}
.frame(width: 133, height: 56, alignment: .center)
.foregroundColor(.blue)
.background(Color.loginButtonBackgroundColor)
.cornerRadius(27.5)
.opacity(1)
}
}
}
And here's how it looks like atm:
I don't understand how to translate x:10 & y:20 to SwiftUI code and also can't find the way to blur the shadow (20%). Any ideas are welcome.
Also can't figure out why that RoundedRectangle stays visible after i put VStack on top of it.. I was thinking it will hide everything but the shadow below the button.
As far as I see there are two issues here to be fixed (although of course I don't have your colors and images):
ZStack {
RoundedRectangle(cornerRadius: 27.5)
.fill(Color.dropShadowColor) // << here fill, not stroke !!
.frame(width: 133, height: 56, alignment: .center)
.shadow(color: .black, radius: 2, x: 0, y: 2) // << no offset by x
VStack {
VStack {
Image(imageName)
.resizable()
.scaledToFit()
}
.frame(height: 28, alignment: .center)
}
.frame(width: 133, height: 56, alignment: .center)
.foregroundColor(.blue)
.background(Color.loginButtonBackgroundColor) // << should be opaque color !!
.cornerRadius(27.5)
.opacity(1)
}

Force SwiftUI view to overflow in trailing direction instead of expanding in both directions

I have a SwiftUI view in an HStack that will be wider than it's parent. When this happens, the HStack expands in both leading and trailing directions, despite being put in a VStack with alignment set to .leading (which I had hoped would anchor the leading edge).
Consider the following simplified Playground code:
import SwiftUI
import PlaygroundSupport
struct TestView : View {
var body: some View {
VStack {
VStack(alignment: .leading) {
HStack {
Rectangle()
.foregroundColor(Color.red)
.frame(width: 20)
Rectangle()
.foregroundColor(.green)
}.frame(height: 40)
HStack {
Rectangle()
.foregroundColor(.orange)
.frame(width: 10)
Rectangle()
.foregroundColor(.green)
.frame(width: 200)
Rectangle()
.foregroundColor(.yellow)
.frame(width: 10)
}
.frame(height: 40)
HStack {
Rectangle()
.foregroundColor(.orange)
.frame(width: 10)
Rectangle()
.foregroundColor(.green)
.frame(width: 200)
Rectangle()
.foregroundColor(.yellow)
.frame(width: 10)
}
.frame(height: 40)
}
.border(Color.red)
}
.frame(width: 300, height: 400)
.border(Color.black)
}
}
// Present the view controller in the Live View window
PlaygroundPage.current.liveView = UIHostingController(rootView: TestView())
In the above example, everything fits within the view and behaves as expected:
However, change the last green Rectangle to a width of 500 instead of 200, and the following happens:
You can see that the orange leading Rectangle has disappeared, pushed off to the left. Similarly, the yellow Rectangle at the end has been pushed to the right.
What I would like to have happen is have the orange Rectangle visible, meaning that all 3 HStacks would have the same x origin (0). So, the result would be seeing the orange Rectangle on the left, the green visible, but spilling over to the right, and the yellow invisible, since it would be pushed off the screen.
I assume this may have to do with using clipped() or fixedSize but I haven't been able to find a working solution yet.
The easiest solution (no workarounds or other views required) is to set the alignment in the frame modifier of the outer VStack to .leading like this:
struct TestView : View {
var body: some View {
VStack {
VStack(alignment: .leading) {
HStack {
Rectangle()
.foregroundColor(Color.red)
.frame(width: 20)
Rectangle()
.foregroundColor(.green)
}.frame(height: 40)
HStack {
Rectangle()
.foregroundColor(.orange)
.frame(width: 10)
Rectangle()
.foregroundColor(.green)
.frame(width: 200)
Rectangle()
.foregroundColor(.yellow)
.frame(width: 10)
}
.frame(height: 40)
HStack {
Rectangle()
.foregroundColor(.orange)
.frame(width: 10)
Rectangle()
.foregroundColor(.green)
.frame(width: 500)
Rectangle()
.foregroundColor(.yellow)
.frame(width: 10)
}
.frame(height: 40)
}
.border(Color.red)
}
.frame(width: 300, height: 400, alignment: .leading) //<= here
.border(Color.black)
}
}
struct TestView : View {
var body: some View {
VStack {
VStack(alignment: .leading) {
HStack {
Rectangle()
.foregroundColor(Color.red)
.frame(width: 20)
Rectangle()
.foregroundColor(.green)
}.frame(height: 40)
HStack {
Rectangle()
.foregroundColor(.orange)
.frame(width: 10)
Rectangle()
.foregroundColor(.green)
.frame(width: 200)
Rectangle()
.foregroundColor(.yellow)
.frame(width: 10)
}
.frame(height: 40)
HStack {
GeometryReader{_ in
Rectangle()
.foregroundColor(.orange)
.frame(width: 10)
.offset(x: 0)
Rectangle()
.foregroundColor(.green)
.frame(width: 500)
.offset(x: 10)
Rectangle()
.foregroundColor(.yellow)
.frame(width: 10)
.offset(x: 510)
}
}
.frame(height: 40)
}
.border(Color.red)
}
.frame(width: 300, height: 400)
.border(Color.black)
}
}