How to add navigation button link in button in SwiftUI? - ios

I want to nagivate to the details screen using button. the buttons are designed in a separate view and called Using ForEach function. Please guide me to solve this.
This is the code I designed for button
struct ButtonsDesignView: View {
var buttons: MyModel.buttons
var body: some View {
Button(action: { }) {
ZStack {
HStack{
VStack{
Text(btn.title)
.foregroundColor(Color(.blue))
.padding()
Text(btn.subtitle)
.foregroundColor(Color(.blue))
.padding()
}
Spacer()
VStack{
Image(systemName: (btn.image))
.resizable()
.scaledToFit()
.foregroundColor(Color(.blue))
.padding()
}
}
}
}
This is code code I've place in ContentView to call display the buttons in scrollview Using ForEach.
ScrollView(.vertical, showsIndicators: false)
{
ForEach(buttonsData) {
item in
NavigationLink(destination: DetailView(buttons: item))
{
ButtonsDesignView(buttons: item)
.padding(10)
}
}.padding(.horizontal, 30)
}
But with this code navigation link is not working.

You should add navigationLink to ButtonDesignView.
I think that this should work;
NavigationLink(destination: DetailView(buttons: buttons)) {
Button(action: { }) {
ZStack {
HStack{
VStack{
Text(btn.title)
.foregroundColor(Color(.blue))
.padding()
Text(btn.subtitle)
.foregroundColor(Color(.blue))
.padding()
}
Spacer()
VStack{
Image(systemName: (btn.image))
.resizable()
.scaledToFit()
.foregroundColor(Color(.blue))
.padding()
}
}
}
}
}

Related

How to create design covering back button and top bar fully with cross button above it?

I am trying to create below design using swiftUI but not able to find proper approach.
I tried but my image is not covering back button but coming below to back button
Expected design
VStack(spacing: 16) {
VStack {
ZStack(alignment: .topTrailing) {
Image("defaultImage")
.resizable()
.frame( height: 200)
Button("Cancel", action: {
print("cancel")
})
.padding(12)
}
}
}
My Design :(
You might want to do a lot of try in SwiftUI to get a custom design right. gave it a quick try for you and added comments on the code so you can understand most of what i did.
this is the quick result i got (with a random background i got on internet)
import SwiftUI
struct FirstView: View{
var body: some View{
NavigationView {
VStack{
NavigationLink(destination: BackgroundImageNav()){
Text("Go to the view")
.font(.title)
}
}
}
}
}
struct BackgroundImageNav: View {
#Environment(\.presentationMode) var presentationMode
// remplacing the back button action, (only problem is that this disable the swipe back)
var body: some View {
ZStack {
// ZStack help you having your image behind the other views
VStack {
Image("defaultImage")
.resizable()
.frame(height: 180)
.edgesIgnoringSafeArea(.all)
Spacer()
// having a spacer that push the image on the top and ignoring the safe area
}
VStack(alignment:.leading){
HStack{
Button(action:{
presentationMode.wrappedValue.dismiss()
// back button action
}){
Image(systemName:"chevron.left")
.resizable()
.aspectRatio(contentMode: .fit)
.frame(width: 30, height: 30)
.foregroundColor(.white)
}
Spacer()
Rectangle()
.fill(Color.white)
.frame(width: 200, height: 80, alignment: .center)
Spacer()
Button(action:{
// do something
}){
Image(systemName: "xmark")
.resizable()
.frame(width: 24, height: 24)
.foregroundColor(.white)
}
}.padding()
Text("Title")
.bold()
.font(.title)
.foregroundColor(.black)
.background(Color.white)
.padding(24)
Spacer()
}
}.navigationBarHidden(true)
// removing the bar to customize the back button
}
}
struct backgroundImage_Previews: PreviewProvider {
static var previews: some View {
FirstView()
}
}

SwiftUI: Why does an EnvironmentalObject get reinitialized when you interact with a TextField in this navigation flow?

In my app you go through the onboarding during sign-up. That works perfectly. However, you can go through it again via the Profile Page.
The profile page code in question looks like this (embedded in a top-level NavigationView of course)
NavigationLink(destination:
EndDateView().environmentObject(OnboardingVM(coordinator: viewModel.appCoordinator))
) {
HStack {
Image(systemName: "chart.pie.fill")
.font(.title)
Text("Edit Spending Plan")
.fontWeight(.bold)
.scaledFont("Avenir", 20)
}
}
.buttonStyle(ButtonWithIcon())
This leads you to a screen where you set a Date via a date picker. All is good at this point.
When you navigate to the third page of this flow (Profile -> Datepicker -> Set Income) and interact with a SwiftUI TextField, the #EnvironmentObject reinitializes itself.
Below you will see the code snippets that show how we navigate/pass the env object around
DatePicker Navigation Code
NavigationLink(destination: SetIncomeView().environmentObject(onboardingVM)) {
PurpleNavigationButton(buttonText: onboardingVM.continueButton)
}
SetIncome Code
struct SetIncomeView: View {
#EnvironmentObject var onboardingVM: OnboardingVM
#ObservedObject var setIncomeVM = SetIncomeVM()
var body: some View {
VStack {
HStack {
CustomHeader1(text: SetIncomeContent.title)
Button(action: {
setIncomeVM.info.toggle()
}) {
Image(systemName: "info.circle")
}
}
.alert(isPresented: $setIncomeVM.info) {
Alert(title: Text(SetIncomeContent.title),
message: Text(SetIncomeContent.header),
dismissButton: .default(Text(SetIncomeContent.dismiss)))
}.padding()
Spacer()
ScrollView {
HStack {
CustomHeader2(text: SetIncomeContent.income)
TextField("", text: $onboardingVM.expectedIncomeAmount)
.keyboardType(.numberPad)
.frame(width: 100, height: 35, alignment: .center)
.scaledFont("Avenir", 20)
.textFieldStyle(RoundedBorderTextFieldStyle())
}
HStack {
CustomHeader2(text: SetIncomeContent.onBasis)
Picker(selection: $onboardingVM.selectedBasis, label: Text("")) {
ForEach(0 ..< self.onboardingVM.basis.count) {
Text(self.onboardingVM.basis[$0])
}
}
.frame(width: 100)
.clipped()
CustomHeader2(text: SetIncomeContent.basis)
}
Button(action: {
setIncomeVM.otherIncome.toggle()
}) {
if setIncomeVM.otherIncome {
Image(systemName: "minus.circle")
} else {
Image(systemName: "plus.circle")
}
Text(SetIncomeContent.anotherSource)
.foregroundColor(.black)
.underline()
.fixedSize(horizontal: false, vertical: true)
.padding()
}
//TODO: I am getting a bug where if i type or scroll it closes the view below
HStack {
CustomHeader2(text: SetIncomeContent.income)
TextField("", text: $onboardingVM.additionalIncome)
.keyboardType(.numberPad)
.frame(width: 100, height: 35, alignment: .center)
.scaledFont("Avenir", 20)
.textFieldStyle(RoundedBorderTextFieldStyle())
}.isHidden(!setIncomeVM.otherIncome)
HStack {
CustomHeader2(text: SetIncomeContent.onBasis)
Picker(selection: $onboardingVM.additionalBasis, label: Text("")) {
ForEach(0 ..< self.onboardingVM.basis.count) {
Text(self.onboardingVM.basis[$0])
}
}
.frame(width: 100)
.clipped()
CustomHeader2(text: SetIncomeContent.basis)
}.isHidden(!setIncomeVM.otherIncome)
}
Spacer()
NavigationLink(destination: SetSavingsView().environmentObject(onboardingVM),
isActive: $setIncomeVM.savingsLink1Active) {
Button(action: {
setIncomeVM.savingsLink1Active.toggle()
}) {
Text(SetIncomeContent.noIncome)
.foregroundColor(.black)
.underline()
.fixedSize(horizontal: false, vertical: true)
.padding()
}
}
NavigationLink(destination: SetSavingsView().environmentObject(onboardingVM), isActive: $setIncomeVM.savingsLink2Active) {
Button(action: {
self.onboardingVM.saveIncomeBasis()
if !setIncomeVM.savingsLink2Active {
setIncomeVM.savingsLink2Active.toggle()
}
}) {
PurpleNavigationButton(buttonText: onboardingVM.continueButton)
}
}
}
Spacer()
}
}
Any idea why this happens?

Applying resizable() on an Image affects text in SwiftUI

I am working on SwiftUI to make a widget and I can't figure out if I'm doing something wrong or there's a bug in SwiftUI.
I have an Image that I use as a background and at the top there's a text. If I apply resizable() to the Image it also affects the behaviour of the text.
var body: some View {
ZStack {
VStack {
Image(affirmation.customImageName ?? "c_0")
.resizable()
.scaledToFill()
.clipped()
}
HStack {
Text(affirmation.title)
.font(.body)
.multilineTextAlignment(.leading)
.lineLimit(nil)
Spacer()
}
.padding(.leading, 5)
.padding(.top, 5)
}
}
Creates this view:
While this code:
var body: some View {
ZStack {
VStack {
Image(affirmation.customImageName ?? "c_0")
.scaledToFill()
.clipped()
}
HStack {
Text(affirmation.title)
.font(.body)
.multilineTextAlignment(.leading)
.lineLimit(nil)
Spacer()
}
.padding(.leading, 5)
.padding(.top, 5)
}
}
Creates this view:

View with fullscreen image and navigationLink

i'm new to swiftui and struggling with some basic stuff
I'm trying to create a view with 2 buttons on the botton.
I want an image as background of the whole view.
var body: some View {
ZStack {
Image("bg-welcome").edgesIgnoringSafeArea(.all)
}
}
This works fine
I set my view like this
NavigationView {
ZStack {
VStack(alignment: HorizontalAlignment.leading, spacing: 10) {
Text("1").foregroundColor(.white)
Text("2").foregroundColor(.white)
Spacer()
Button(action: {}){
Text("ooooooooo")
}
}.background(Image("bg-welcome"))
}
}
Now I have 2 problems:
- a white space is dispalyed just before the background image
- the first text is pushed below, surely after the space reserved for the navigationbar and I don't want it because when I navigate to the next screen, the space is still taken and I want to have the whole avaiblable screen
thank you for your help
try this:
var body: some View {
NavigationView {
ZStack {
VStack(alignment: HorizontalAlignment.leading, spacing: 10) {
Text("1").foregroundColor(.white)
Text("2").foregroundColor(.white)
Spacer()
Button(action: {}){
Text("Button 1")
}
Button(action: {}){
Text("Button 2")
}
}.background(Image("remachine_poster")
.resizable()
.aspectRatio(contentMode: .fill)).edgesIgnoringSafeArea(.all)
}
}
}
you can add a padding to your button....
NavigationView {
ZStack {
VStack() {
Text("1").foregroundColor(.green).padding(.top, 40)
Text("2").foregroundColor(.green)
Spacer()
Button(action: {}){
Text("Button 1")
}.foregroundColor(Color.red)
Button(action: {}){
Text("Button 2")
}.foregroundColor(Color.red)
}
}.background(Image("remachine_poster")
.resizable()
.aspectRatio(contentMode: .fill))
.edgesIgnoringSafeArea(.vertical)
}
I ended up doing something like this.
Please let me know if there is a better way
NavigationView {
GeometryReader { gr in
ZStack {
VStack(alignment: HorizontalAlignment.center, spacing: 10) {
HStack{
Spacer()
}
Text("1").foregroundColor(.white).padding(EdgeInsets(top: 30, leading: 0, bottom: 0, trailing: 0))
Text("2").foregroundColor(.white)
Spacer()
HStack {
NavigationLink(destination: SigninScreen()){
Text("Button 1")
}
Button(action: {}){
Text("Button 2")
}
}.padding()
}.background(Image("bg-welcome")
.resizable()
.aspectRatio(contentMode: .fill)).edgesIgnoringSafeArea(.all)
}.navigationBarHidden(true)
}
}

Remove circular button background in SwiftUI (WatchKit)

I'm struggling to remove the background of a custom circular Button element in SwiftUI which is defined as follows:
struct NavButton: View {
var body: some View {
Button(action: {})
VStack {
Text("Button")
}
.padding(40)
.background(Color.red)
.font(.title)
.mask(Circle())
}
}
}
This results in a rectangular light gray background around the button, where I want it to not be shown:
I tried to append a "background" modifier to the button, and it demonstrates very strange behavior: if it's set to "Color.clear", there is no effect. But if I set it to "Color.green" it does change the background as expected.
Example of setting the "Background" modifier to "Color.green":
struct NavButton: View {
var body: some View {
Button(action: {})
VStack {
Text("Button")
}
.padding(40)
.background(Color.red)
.font(.title)
.mask(Circle())
}
.background(Color.green) // has no effect if set to "Color.clear"
}
}
I wonder if I'm missing something here?
PS: I'm using Xcode 11.1 (11A1027)
Try adding .buttonStyle(PlainButtonStyle()) on the button itself.
You would have something like this:
Button(action: {}){
VStack{
Text("Button")
}
.padding(40)
.background(Color.red)
.font(.headline)
.mask(Circle())
}
.buttonStyle(PlainButtonStyle())
Declare your own ButtonStyle:
struct RedRoundButton: ButtonStyle {
func makeBody(configuration: Configuration) -> some View {
configuration.label
.padding(40)
.font(.title)
.background( Circle()
.fill(Color.red))
}
}
and then use it like this:
Button("Button") {}
.buttonStyle(RedRoundButton())
Try this:
struct ContentView: View {
var body: some View {
Button(action: {}) {
Text("Button")
.frame(width: 80, height: 80)
}
.background(Color.red)
.cornerRadius(40)
.frame(width: 80, height: 80)
}
}
Try this.
struct ContentView: View {
var body: some View {
VStack {
Button(action: {}){
Text("button")
.font(.system(size: 50))
.foregroundColor(.black)
.bold()
}
.padding(30)
.background(Color.yellow)
.font(.headline)
.mask(Circle())
.buttonStyle(PlainButtonStyle())
} // end Vstack
}// end body
}

Resources