Button with image for SwiftUI 2 - swiftui

I want to add button with image inside of the view like twitter button with image for SwiftUI 2, but it is not padding to any directions.
struct WeatherView: View {
var body: some View {
VStack(alignment: .leading, spacing:0){
Button(action: {}) {
Image("cloud")
.padding()
.background(Color.blue)
.foregroundColor(Color.white)
.clipShape(Circle())
.shadow(radius: 8)
}
HStack(spacing: 5){
Text("Rainy")
.font(.largeTitle)
.fontWeight(.medium)
Spacer()
Button(action: {
}) {
Image("menu").resizable().frame(width: 24, height: 24)
}
}
.foregroundColor(Color("black"))
.padding()
Spacer()
}
}
}
Is there any solution for this problem.

I hope you are doing well.
This code should do the trick.
VStack {
Spacer()
Button(action: {}) {
Image(systemName: "cloud.fill")
.padding()
.background(Color.blue)
.foregroundColor(Color.white)
.clipShape(Circle())
.shadow(radius: 8)
}
}
.frame(maxWidth: .infinity, alignment: .trailing)
.padding()
By putting the button in a VStack, and putting a spacer before it, you will push the button to the bottom of the screen. Then by putting a frame on it, and making the width to be .infinity, and giving it alignment trailing, you will further push the button to the trailing side of the screen, which in this case results in making the button at the bottom right corner.
Edit: Included full code
struct WeatherView: View {
var body: some View {
VStack(alignment: .leading, spacing: 0) {
HStack(spacing: 5) {
Text("Rainy")
.foregroundColor(.black)
.font(.largeTitle)
.fontWeight(.medium)
Spacer()
Button(action: {}) {
Image("menu").resizable().frame(width: 24, height: 24)
}
}
.foregroundColor(Color("black"))
.padding()
VStack {
Spacer()
Button(action: {}) {
Image("cloud")
.padding()
.background(Color.blue)
.foregroundColor(Color.white)
.clipShape(Circle())
.shadow(radius: 8)
}
}
.frame(maxWidth: .infinity, alignment: .trailing)
.padding()
}
}
}

Related

Align text to the left regardless of how much text is shown in a VStack in SwifUI

How can I force the text to always align to the left regardless of how big is the text?
What I get is what's shown in the first image, what I need is to align it to look like the second image.
struct GeneralTest: View {
let fruits = ["Apple", "Oranges from Californ"]
var body: some View {
List {
ForEach(fruits, id: \.self) { fruit in
HStack{
Image(systemName: "pencil.circle.fill")
.frame(width: 65)
.foregroundColor(.blue)
.background(.yellow)
VStack(alignment: .leading){
Text(fruit)
.font(.title3)
.foregroundColor(Color.blue)
VStack(alignment: .leading) {
Text("Some text")
.foregroundColor(Color.gray)
.font(.caption)
Text("Some text:")
.foregroundColor(Color.gray)
.font(.caption)
Text("Some Text:")
.foregroundColor(Color.gray)
.font(.caption)
}
}
.frame(maxWidth: .infinity)
.background(.yellow)
Button{
}label:{
Image( systemName: "circle.hexagongrid.circle")
.padding()
.background(Color.yellow)
.foregroundColor( Color.blue)
.cornerRadius(30)
.overlay(
Circle()
.stroke( Color.gray, lineWidth: 0.5)
)
}
NavigationLink(destination: SomeView()){
}
.frame(maxWidth: 10)
}
} // ForEach end
}
.background(Color.pink)
.listStyle(GroupedListStyle())
}
}
Wrap the "fruit" VStack inside an HStack, then use a Spacer() to move the text to the left.
Like this:
ForEach(fruits, id: \.self) { fruit in
HStack{
Image(systemName: "pencil.circle.fill")
.frame(width: 65)
.foregroundColor(.blue)
.background(.yellow)
// The VStack is inside an HStack
HStack {
VStack(alignment: .leading){
Text(fruit)
.font(.title3)
.foregroundColor(Color.blue)
VStack(alignment: .leading) {
Text("Some text")
.foregroundColor(Color.gray)
.font(.caption)
Text("Some text:")
.foregroundColor(Color.gray)
.font(.caption)
Text("Some Text:")
.foregroundColor(Color.gray)
.font(.caption)
}
}
// This Spacer() will push the VStack to the left
Spacer()
}
.frame(maxWidth: .infinity)
.background(.yellow)
Button{
}label:{
Image( systemName: "circle.hexagongrid.circle")
.padding()
.background(Color.yellow)
.foregroundColor( Color.blue)
.cornerRadius(30)
.overlay(
Circle()
.stroke( Color.gray, lineWidth: 0.5)
)
}
NavigationLink(destination: SomeView()){
}
.frame(maxWidth: 10)
}
} // ForEach end

HStack background color blending into safe area

I am trying to prevent the background of my HStack from going into my safearea.
There is a ZStack that is setting the background color. I am using green just to be more defined for now.
struct AccountView: View {
var body: some View {
ZStack{
Color(.green)
.ignoresSafeArea()
VStack(spacing: 32){
HStack {
Image(systemName: "person")
.resizable()
.scaledToFill()
.frame(width: 64, height: 64)
.clipShape(Circle())
.padding(.leading)
VStack(alignment: .leading, spacing: 4) {
Text("First Last")
.font(.system(size: 18))
Text("Available")
.foregroundColor(.gray)
.font(.system(size: 14))
}
Spacer()
}
.frame(height: 80)
.background(Color("ItemBG"))
Spacer()
}
}
}
}
We need to use shape as background instead of pure-colour, then it is not spread outside.
Here is simplified demo. Tested with Xcode 13.2 / iOS 15.2
var body: some View {
VStack {
HStack {
Text("Hello")
}
.frame(maxWidth: .infinity, maxHeight: 80)
.background(Rectangle().fill(.yellow)) // << here !!
Spacer()
}
.background(Color.green.ignoresSafeArea())
}
I was able to figure it out...
I had to give by HStack a padding of 1 on the top. Apparently with IOS 15 if it touches the safe area it bleeds.
HStack {
Image(systemName: "person")
.resizable()
.scaledToFill()
.frame(width: 64, height: 64)
.clipShape(Circle())
.padding(.leading)
VStack(alignment: .leading, spacing: 4) {
Text("First Last")
.font(.system(size: 18))
Text("Available")
.foregroundColor(.gray)
.font(.system(size: 14))
}
Spacer()
}
.frame(height: 80)
.background(Color("ItemBG"))
.padding(.top, 1)

How fix Stacks to top and bottom using SwiftUI

how are you ?
I need to fit all the content of first zstack (I use two zstack to add a transparent layer over first zstack background) to window size and if the user scroll down, shows additional stacks added below.
I add Spacer() to push the last HStack to bottom and before stacks to the top (in middle must be a dynamic blank space) of window without result.
Can help me please ?
Thanks
ScrollView(.vertical) {
ZStack {
bgColors[weatherDescription]
ZStack {
LinearGradient(gradient: Gradient(colors: [Color(hex: 0x212121, alpha: 0.5), Color(hex: 0x212121, alpha: 0.5)]), startPoint: .top, endPoint: .bottom)
VStack(alignment: .leading) {
Text("Hello!")
.foregroundColor(Color.white)
.fontWeight(.heavy)
.font(.largeTitle)
.padding(.top, 20)
.padding(.bottom, 1)
Text("Hello!")
.foregroundColor(Color.white)
.font(.title)
.padding(.bottom, 1)
Text("Hello!")
.foregroundColor(Color.white)
.font(.title3)
.padding(.bottom, 20)
HStack(alignment: .center, content: {
Text("TEXT1")
.foregroundColor(Color.white)
.font(.title3).fontWeight(.bold)
.frame(maxWidth: .infinity, alignment: .leading)
Text("TEXT2")
.foregroundColor(Color.white)
.font(.title3).fontWeight(.bold)
.frame(maxWidth: .infinity, alignment: .trailing)
}).frame(maxWidth: .infinity)
Spacer()
HStack(alignment: .center, spacing: 30, content: {
Text("Text1")
.foregroundColor(Color.white)
.font(.system(size: 90))
Text("Text2")
.foregroundColor(Color.white)
.font(.caption)
.animation(.easeIn)
}).frame(width: .infinity, alignment: .bottom)
}.padding() // vstack
}.edgesIgnoringSafeArea(.top) // zstack
}.edgesIgnoringSafeArea(.top) // zstack
// ADITIONALS STACKS VISIBLES ONLY WHEN SCROLL DOWN
}
You just used so many codes, I edited them to less code, here for example you just used so many foregroundColor which you can see in my code I used just one time on parent View.
Also we can not use ScrollView like you used it! ScrollView needs Content to Scroll, you have less Content.
import SwiftUI
struct ContentView: View {
var body: some View {
ZStack {
LinearGradient(gradient: Gradient(colors: [Color.red, Color.purple]), startPoint: .top, endPoint: .bottom)
.ignoresSafeArea()
VStack(alignment: .leading, spacing: 30) {
Text("Hello!")
.fontWeight(.heavy)
.font(.largeTitle)
Text("Hello!")
.font(.title)
Text("Hello!")
.font(.title3)
HStack {
Text("TEXT1")
.font(.title3)
.fontWeight(.bold)
Spacer()
Text("TEXT2")
.font(.title3)
.fontWeight(.bold)
}
Spacer()
HStack {
Text("Text1")
.font(.system(size: 90))
Spacer()
Text("Text2")
.font(.caption)
}
}
.padding()
}
.foregroundColor(Color.white)
.animation(.easeIn)
}
}

ScrollView text alignment SwiftUI

I have a vertical ScrollView with a ForEach loop that has HStack's inside with Text, Image, and Two Text's. I'd like to keep each row's items in alignment with each other. I've attempted to wrap in a VStack with alignment .leading but did nothing. The issue I'm having is the text doesn't line up. Still very new to SwiftUI so any help would be appreciated.
ScrollView(.vertical) {
ForEach(self.daily.forecast, id: \.date) { forecast in
HStack (spacing : 10){
Text(forecast.date ?? "")
.fontWeight(.bold)
Spacer()
RequestImage(Url("IMAGE_URL"))
.aspectRatio(contentMode: .fit)
.frame(width: 30, height: 30)
.clipped()
Spacer()
Text("\(forecast.maxTemp)")
.fontWeight(.bold)
Text("\(forecast.minTemp)")
.fontWeight(.bold)
}
}
}
.padding(.all, 15)
.onAppear() {
authorize {_ in
loadForecast()
}
}
UPDATED:
I was able to get a bit closer but things still aren't aligned to where I'd like them to be.
ScrollView(.vertical) {
ForEach(self.daily.forecast, id: \.date) { forecast in
HStack (spacing : 10){
Text(date)
.font(.title3)
.fontWeight(.bold)
.frame(minWidth: 45)
Spacer()
RequestImage(Url("IMAGE_URL"))
.aspectRatio(contentMode: .fit)
.frame(width: 35, height: 35)
.frame(minWidth: 50)
.clipped()
Spacer()
Text(maxTemp)
.font(.title3)
.fontWeight(.bold)
.frame(minWidth: 45)
Text(minTemp)
.font(.title3)
.fontWeight(.bold)
.foregroundColor(Color.secondary)
.frame(minWidth: 45)
}
.frame(minWidth: 0, maxWidth: .infinity, alignment: .leading)
}
}
.padding(.all, 15)
.onAppear() {
authorize {_ in
loadForecast()
}
}
Here is a demo of possible solution. Prepared with Xcode 12.4 / iOS 14.4
struct DemoWeatherLayout: View {
private var dayOfTheWeek = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sut"]
var body: some View {
ScrollView {
VStack {
ForEach(dayOfTheWeek, id: \.self) {
WeatherRowView(day: $0,
icon: ["sun.max", "cloud.sun", "cloud", "cloud.snow"].randomElement()!,
low: Array(-5..<0).randomElement()!,
high: Array(1..<15).randomElement()!)
}
}.padding()
}
}
}
struct WeatherRowView: View {
var day: String
var icon: String
var low: Int
var high: Int
var body: some View {
HStack {
Text(day)
.frame(maxWidth: .infinity, alignment: .leading)
Image(systemName: icon)
.frame(maxWidth: .infinity, alignment: .leading)
HStack {
Text("+XXº").foregroundColor(.clear)
.overlay(Text(String(format: "%+d", low)), alignment: .leading)
Text("+XXº").foregroundColor(.clear)
.overlay(Text(String(format: "%+d", high)), alignment: .leading)
}
}
}
}
Three suggestions:
add alignment parameter to HStack:
HStack(alignment: .lastTextBaseline, spacing: 10) { ... //others options: .top, .center, .firstTextBaseline...
Add minLength parameter to Spacer:
Spacer(minLength: 0) but with spacing: 10 in HStack it is a bit redundant. You can remove spacing: 10 for Spacer(minLength: 10)
Add a Spacer(minLength: 0) at the end after Text("\(forecast.minTemp)").fontWeight(.bold)
I'm going to accept #Asperi answer as correct. The UI has indeed changed since to better fit said labels etc. Appreciate everyone's else. The code is very much ugly but works. Not sure if it's 100% correct.
HStack (spacing: 10){
Text(date)
.font(.title3)
.fontWeight(.bold)
.frame(minWidth: 0, maxWidth: .infinity, alignment: .leading)
Spacer()
RequestImage(Url("IMAGE_URL_HERE"))
.aspectRatio(contentMode: .fit)
.frame(width: 35, height: 35)
.frame(minWidth: 55)
.clipped()
Spacer()
Text(maxTemp)
.font(.title3)
.fontWeight(.bold)
.frame(minWidth: 50)
.background(Color.orange)
.cornerRadius(5)
Text(minTemp)
.font(.title3)
.fontWeight(.bold)
.frame(minWidth: 50)
.background(Color.blue)
.cornerRadius(5)
}

SwiftUI: How to restrict view to only resizing in one direction?

How can I restrict the view to resize only downwards?
I am trying to add more buttons & have the view resize to accommodate the buttons without overlapping the red rectangle above.
This is the code I am currently using:
struct ContentView: View {
var body: some View {
VStack{
RoundedRectangle(cornerRadius: 20)
.frame(width: .infinity, height: 55)
.foregroundColor(.red)
HStack{
Spacer()
ZStack{
RoundedRectangle(cornerRadius: 20)
.foregroundColor(.green)
VStack{
Button(action: {}) {
Text("Test Button")
.foregroundColor(.white)
.font(.headline)
.frame(width: .infinity)
Spacer()
}.padding()
Button(action: {}) {
Text("Test Button")
.foregroundColor(.white)
.font(.headline)
.frame(width: .infinity)
Spacer()
}.padding()
Button(action: {}) {
Text("Test Button")
.foregroundColor(.white)
.font(.headline)
.frame(width: .infinity)
Spacer()
}.padding()
}
}.frame(width: 250, height: 100)
}
Spacer()
}
}
}
Change your .frame(width: 250, height: 100) to .frame(width: 250, height: 100, alignment: .top) Your original example defaults to .center, which is why it expands into the red rectangle.