SwiftUi bottom left button dont show - swift

I have some SwiftUI function. I want to show my button in bottom left, but it shows top left.
struct NewRecordButton: View {
var body: some View {
ZStack (alignment: .bottomTrailing) {
HStack (alignment: .bottom) {
Spacer()
Button(action: { },
label: {
Text("⌂")
.font(.system(.largeTitle))
.frame(width: 35, height: 30)
.foregroundColor(Color.white)
.padding(.bottom,4)
}) .background(Color.black)
.cornerRadius(10)
.shadow(color: Color.black.opacity(0.3),
radius: 3,
x: 3,
y: 3)
}
}
}
}
Any ideas?

Here is possible variant
ZStack (alignment: .bottomTrailing) {
Rectangle().fill(Color.clear)
HStack (alignment: .bottom){
Button(action: {
}, label: {
Text("⌂")
.font(.system(.largeTitle))
.frame(width: 35, height: 30)
.foregroundColor(Color.white)
.padding(.bottom,4)
})
.background(Color.black)
.cornerRadius(10)
.shadow(color: Color.black.opacity(0.3),
radius: 3,
x: 3,
y: 3)
Spacer()
}
}

Although it's possible, but you should try NOT to use dummy views to arrange other views!
For pushing a view down, you should use a VStack and a Spacer together
VStack {
Spacer()
// bottomView
}
So it should be like:
ZStack {
VStack {
Spacer() // This will push it down, since it is in a `VStack`
HStack {
Button("⌂") {}
.font(.largeTitle)
.frame(width: 35, height: 30)
.foregroundColor(.white)
.padding(.bottom, 4)
.background(Color.black)
.cornerRadius(10)
.shadow(color: Color.black.opacity(0.3), radius: 3, x: 3, y: 3)
Spacer() // This will push it left, since it is in a `HStack`
}
}
}

Related

How do I Fix the alignment of this swiftUI view

I'm trying to put a number of DateCardViews inside a ScrollView as shown below
How do I fix the alignment DateCardView, so all DateCardViews are anchored to the top and start at the same level?
var body: some View {
VStack(alignment: .leading, spacing: 0) {
ScrollView(.horizontal, showsIndicators: false) {
HStack(alignment: .top) {
ForEach(dates.prefix(8), id: \.id) { date in
DateCardView(meetDate: date)
}
}
.padding(.horizontal, 16.0)
}
.padding(.bottom, 20.0)
}
}
struct DateCardView: View {
#State var meetDate: MeetDate
#State var swap = false
var isExpired: Bool {
Date.isAboutToExpire(date: meetDate.date)
}
var body: some View {
VStack {
Image(swap ? meetDate.user.profileImages.first! : meetDate.bgIamge)
.resizable()
.cornerRadius(16)
.overlay(
Image((swap ? meetDate.bgIamge : meetDate.user.profileImages.first!))
.resizable()
.cornerRadius(6)
.frame(width: 32, height: 40)
.padding(.bottom, 8)
.padding(.trailing, 8)
.onTapGesture {
swap.toggle()
}, alignment: .bottomTrailing
)
.frame(height: 154)
VStack(alignment: .leading) {
HStack {
Text(meetDate.title)
.font(.custom("SFCompactText-Medium", size: 18))
.lineLimit(2)
}
HStack {
Text(Date.yearString(date: meetDate.date))
Text(Date.timeString(date: meetDate.date))
.foregroundColor(isExpired ? Color("Expired") : Color.black)
Spacer()
}.font(.custom("SFCompactText-Medium", size: 14))
HStack {
Text(meetDate.length)
.font(.custom("SFCompactText-Medium", size: 12))
Text(meetDate.cost)
.font(.custom("SFCompactText-Medium", size: 12))
.foregroundColor(Color("cost"))
}
}
}.frame(width: 138, height: 235)
}
}
You can probably fix this by adding a Spacer at the bottom of your outer VStack, but as the code in your question won't compile I can't test it,
VStack {
Image(swap ? meetDate.user.profileImages.first! : meetDate.bgIamge)
//
VStack(alignment: .leading) {
// etc
}
Spacer(minLength: 0)
}.frame(width: 138, height: 235)
You can add Spacer() in your Vstack. I think that will work or you can change your alingment values.
VStack(alignment: .leading) {
//your code
Spacer()
}

Why does ScrollView randomly push my views content downwards?

Here is my code:
import SwiftUI
struct TrendingView : View {
#State var selectedTab: Tabs = .hot
#State private var searchText = ""
var body: some View {
NavigationView {
VStack {
HStack {
Text(" Trending")
.font(.largeTitle)
.frame(width: 175, height: 50, alignment: .leading)
.overlay(
RoundedRectangle(cornerRadius: 5)
.stroke(.black, lineWidth: 2)
)
.italic()
.fontWeight(.heavy)
.foregroundColor(Color(hue: 1.0, saturation: 0.977, brightness: 0.985))
.offset(x: -75, y: -25)
.padding(.bottom, -20)
NavigationLink(destination: testT()) {
Image(systemName: "magnifyingglass.circle.fill")
.resizable()
.scaledToFit()
.frame(width: 40, height: 40)
.foregroundColor(.black)
.padding(.bottom, -20)
}
.offset(x: 50, y: -25)
.padding(.leading, 5.0)
}
ScrollView {
VStack {
Text("Hot Items 🔥")
.bold()
.italic()
.offset(x: 5)
.frame(width: 120, height: 25, alignment: .leading)
.overlay(
RoundedRectangle(cornerRadius: 5)
.stroke(.black, lineWidth: 2)
)
.background(.yellow)
.offset(x: -130, y: 5)
ScrollView(.horizontal) {
HStack {
NavigationLink(destination: ImageTest()) {
Image("testpic1")
.resizable()
.frame(width: 200, height: 200)
}
NavigationLink(destination: ImageTest()) {
Image("testpic3")
.resizable()
.frame(width: 200, height: 200)
}
}.offset(y: 30)
}
}
}
There seems to be some error with scrollview above my vstack as it randomly causes all the content on this view to shift downwards when switching to and from other views.Ive tried removing the scrollview and the error disappears and also tried changing it around in other places but I still get the error Can anybody point me in the right direction? Thanks
Fixed, added to the bottom of my code and it seems like the issue is solved
.navigationBarTitle(Text(""), displayMode: .inline)
.navigationBarHidden(true)

Swift ui widget list of items that take up too much space

As you can see from the image I have a widget with a series of elements, I have to put at the end of the series of elements then the word Next update which must find some at the end of the widget.
The problem is:
if there are few elements, Next update is too high.
if there are many elements the Next update message is not shown.
Can you give me a hand?
P.s.
If you think it should be written differently let me know, thank you in advance.
struct GitCommitWidgetEntryView : View {
var entry: ProviderCommit.Entry
#Environment(\.colorScheme) var colorScheme
let firstColor: UInt = getDate() ? 0x4688B4 : 0x030721
var body: some View {
GeometryReader { geometry in
if(entry.loading){
if(!entry.error){
VStack() {
if(entry.user != ""){
HStack {
Spacer()
Text("\(entry.user) (\(entry.commits.count))")
.font(.caption)
.foregroundColor(Color.black)
.shadow(
color: Color.black,
radius: 1.0,
x: CGFloat(1),
y: CGFloat(1)
)
Spacer()
}
.background(Color(hex: 0xff9800))
}
if(entry.commits.count > 0){
ForEach(entry.commits, id:\.id){
item in
Text(item.commit.message)
.shadow(
color: Color.black,
radius: 1.0,
x: CGFloat(1),
y: CGFloat(1)
)
Text("\(item.author.login) \(convertDate(date: item.commit.author.date))")
.shadow(
color: Color.black,
radius: 1.0,
x: CGFloat(1),
y: CGFloat(1)
)
Divider()
}
.frame(alignment: /*#START_MENU_TOKEN#*/.center/*#END_MENU_TOKEN#*/)
}else{
Text("There are no repositories.")
.font(.caption)
.foregroundColor(Color.black)
.padding(2)
.background(Color.white.opacity(0.4))
.cornerRadius(5)
.padding(.bottom, 3)
.padding(.horizontal, /*#START_MENU_TOKEN#*/10/*#END_MENU_TOKEN#*/)
.multilineTextAlignment(.center)
.frame(maxWidth: .infinity, maxHeight: /*#START_MENU_TOKEN#*/.infinity/*#END_MENU_TOKEN#*/, alignment: /*#START_MENU_TOKEN#*/.center/*#END_MENU_TOKEN#*/)
}
HStack {
Spacer()
Text("Next update")
.font(.caption)
.foregroundColor(Color.black)
.multilineTextAlignment(.center)
.shadow(
color: Color.black,
radius: 1.0,
x: CGFloat(1),
y: CGFloat(1)
)
Spacer()
}
.background(Color(hex: 0xff9800))
}
.background(LinearGradient(
gradient: Gradient(colors: [
Color(hex: firstColor),
Color(hex: 0xffffff)
]),
startPoint: .top,
endPoint: .bottom)
)
}else{
VStack() {
Text("No user exist.")
.font(.caption)
.foregroundColor(Color.black)
.padding(2)
.background(Color.white.opacity(0.4))
.cornerRadius(5)
.padding(.bottom, 3)
.padding(.horizontal, /*#START_MENU_TOKEN#*/10/*#END_MENU_TOKEN#*/)
.multilineTextAlignment(.center)
}
.frame(maxWidth: .infinity, maxHeight: /*#START_MENU_TOKEN#*/.infinity/*#END_MENU_TOKEN#*/, alignment: /*#START_MENU_TOKEN#*/.center/*#END_MENU_TOKEN#*/)
.background(Color.red)
}
}else{
VStack() {
Text("No user selected.")
.font(.caption)
.foregroundColor(Color.black)
.padding(2)
.background(Color.white.opacity(0.4))
.cornerRadius(5)
.padding(.bottom, 3)
.padding(.horizontal, /*#START_MENU_TOKEN#*/10/*#END_MENU_TOKEN#*/)
.multilineTextAlignment(.center)
}
.frame(maxWidth: .infinity, maxHeight: /*#START_MENU_TOKEN#*/.infinity/*#END_MENU_TOKEN#*/, alignment: /*#START_MENU_TOKEN#*/.center/*#END_MENU_TOKEN#*/)
.background(Color.green)
}
}
}
}
The approach you need is to separate "labels to be always on screen" and "growing list", schematically it should be like
VStack {
Text("Header label")
Spacer()
Text("Footer label")
}
.background(
VStack {
Text("Header label").opacity(0) // for content offset
// or constant height spacer
ForEach ... // list here
}
}

SwiftUI unable to align button with topLeading

I have a button which I am unable to align to the top left with topLeading.
What I hope to accomplish:
my code:
var body: some View {
ZStack {
ZStack(alignment: .topLeading) {
Button(action: { self.show.toggle() }) {
HStack {
Spacer()
Image(systemName: "list.dash")
.foregroundColor(.black)
}
.padding(.trailing, 20)
.frame(width: 90, height: 60)
.background(Color.white)
.cornerRadius(30)
.shadow(color: Color("buttonShadow"), radius: 10, x: 0, y: 10)
}
Spacer()
}
}
}
But I get this:
The issue is that your wrapping views (two ZStacks) by default will take up only the space of their content, which is only the button. If you add a frame to allow the wrapper to expand you'll see the alignment working as you expect.
var body: some View {
ZStack {
ZStack {
Button(action: { self.show.toggle() }) {
HStack {
Spacer()
Image(systemName: "list.dash")
.foregroundColor(.black)
}
.padding(.trailing, 20)
.frame(width: 90, height: 60)
.background(Color.white)
.cornerRadius(30)
.shadow(color: Color.gray, radius: 10, x: 0, y: 10)
}
Spacer()
}
.frame(
maxWidth: .infinity,
maxHeight: .infinity,
alignment: Alignment.topLeading
)
}
}
Add background space consumer, like below (tested with Xcode 11.4)
ZStack(alignment: .topLeading) {
Color.clear // << here !!
Button(action: { self.show.toggle() }) {

Align rectangle to be within certain distance of safe area bottom edge SWIFTUI

I am used to Interface Builder and layout constraints but now I want to convert my app to Swift UI. What I am trying to do right now is align the top edge of the view marked with a 1 to be within a certain distance of the safe area bottom edge (marked with a 2) so that the top edge that is now at 1 will then be at position 3. I tried using spacers but then it will look different on smaller devices such as an iPhone 8. In IB I could have used a simple layout constraint. How does this work in Swift UI? I have attached the relevant code and an image. Thank you for your help.
struct ContentView: View {
init() {
UINavigationBar.appearance().backgroundColor = .orange
}
var body: some View {
NavigationView {
VStack{
Spacer()
ZStack{
Rectangle()
.fill(Color(hue: 0, saturation: 0, brightness: 0, opacity: 0.1))
Image("")
.resizable()
.aspectRatio(contentMode: .fit)
.frame(width: 100, height: 150)
.clipShape(Circle())
.overlay(Circle().stroke(Color.white, lineWidth: 4))
.shadow(radius: 10)
}.frame(width: UIScreen.main.bounds.width, height: UIScreen.main.bounds.width, alignment: .center)
Spacer(minLength: 100)
ZStack(alignment: .bottom){
ExtractedView()
.edgesIgnoringSafeArea(.bottom)
}
}
.navigationBarTitle(Text("You See"))
.navigationBarHidden(false)
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
.previewDevice("iPhone")
}
}
struct ExtractedView: View {
#State private var name: String = ""
var body: some View {
VStack{
ZStack(alignment: .top){
VStack{
RoundedRectangle(cornerRadius: 50)
.frame(width: 60, height: 7)
.padding(.top)
Button(action: /*#START_MENU_TOKEN#*/{}/*#END_MENU_TOKEN#*/) {
Text("Start advertising")
.font(.headline)
.foregroundColor(Color.black)
}.padding(.top)
TextField("Test", text: $name)
.padding(.all)
.background(Color.white.cornerRadius(20))
.padding()
}
RoundedRectangle(cornerRadius: 30)
.fill(Color(hue: 0, saturation: 0, brightness: 0, opacity: 0.1))
.zIndex(-5)
}
}
}
}
Ok, so I was able to solve my problem. The trick is to create two VStacks with different frame alignments. The outer VStack has top alignment so that the Discover view can be at the top. The inner VStack has a bottom alignment so that the sheet can be pulled up from the bottom. Space will be filled from the bottom up in this case.
VStack{
Discover()
.padding(.top, 60.0)
VStack{
Text("Recent Messages:")
.font(.headline)
DetailSheet()
.offset(x: 0, y: 0)
}.frame(width: g.size.width, height: (g.size.height - g.size.width - 80 + 200), alignment: .bottom)
}
.frame(width: g.size.width, height: g.size.height, alignment: .top)
you can try this:
offset -10 is just your offset you want to have....
i hope i understood you right, i am not so sure...
var body: some View {
VStack{
// ZStack(alignment: .top){
VStack{
RoundedRectangle(cornerRadius: 50)
.frame(width: 60, height: 7)
.padding(.top)
Button(action: /*#START_MENU_TOKEN#*/{}/*#END_MENU_TOKEN#*/) {
Text("Start advertising")
.font(.headline)
.foregroundColor(Color.black)
}.padding(.top)
TextField("Test", text: $name)
.padding(.all)
.background(Color.white.cornerRadius(20))
.padding()
}.background(RoundedRectangle(cornerRadius: 30)
.fill(Color(hue: 0, saturation: 0, brightness: 0, opacity: 0.1))
).offset(y:-10)
}
// }