How to remove the background in NavigationLinks? - ios

How do I remove the background color of navigation link(The gray stuff).
I have tried setting the background color to clear, but that does not seem to do anything:
struct DesignView: View {
#State var index: Int
#State var selection: Int
var body: some View {
ZStack(alignment: .center){
RoundedRectangle(cornerRadius: 90.0)
.fill(Color.white)
.frame(height: 50)
NavigationLink(
destination: GraphView(type: selection, index: index),
label: {
Text("Warm Up #\(index)")
.font(.system(size: 20, weight: .bold, design: .rounded))
.foregroundColor(.black)
.backgroundStyle(
Color.clear
)
})
.backgroundStyle(
Color.clear
)
.padding()
}
}
}

I found the solution:
Navigation Links respond to tint, not to the bcgrnd color for that purpose:
NavigationLink(
destination: GraphView(type: selection, index: index),
label: {
Text("Warm Up #\(index)")
.font(.system(size: 20, weight: .bold, design: .rounded))
.foregroundColor(.black)
.backgroundStyle(
Color.clear
)
})
.tint(Color.clear)
.backgroundStyle(
Color.clear
)

Related

Why is are the images being cut off?

The images in my 'tiles' are being cut off at the sides. I am trying to create a tile for each 'product' that displays an image, name and subtitle. Everything now works as it should besides the image. This is because the images on the tiles are being cut off at the sides.
The view for the ContentView is as follows:
ScrollView(.vertical, showsIndicators: false, content: {
Spacer()
LazyVGrid(columns: Array(repeating: GridItem(.flexible(),spacing: 15), count: 2),spacing: 10){
ForEach(HomeModel.filteredProduct){product in
// Product View...
ProductView(productData: product)
.background(.white)
.clipShape(RoundedRectangle(cornerRadius: 15, style: .continuous))
.shadow(color: .black.opacity(0.4), radius: 3, x: 1, y: 1)
.onTapGesture {
withAnimation(.easeIn){
selectedProduct = charity
show.toggle()
}
}
}
}
Spacer()
.padding()
.padding(.top,10)
})
.padding(.top, 20)
And the ProductView code is as follows:
var body: some View {
VStack(alignment: .center, spacing: 0) {
WebImage(url: URL(string: productData.product_image))
.resizable()
.aspectRatio(contentMode: .fill)
.frame(width: 160, height: 225)
.cornerRadius(15)
.clipped()
.padding(5)
Text(productData.product_name)
.font(.title2)
.fontWeight(.bold)
.foregroundColor(.black)
.padding()
Text(productData.product_type)
.font(.caption)
.foregroundColor(.gray)
.lineLimit(2)
.padding()
}
}
Here is an image showing what is meant by 'the tile is cutting it off':
As you can see in the photo, the image is not all included because it doesn't fit in the tile. This needs to be resized.
The first issue here would be the .contentMode modifier it needs to be set to fill. If you have an image where the width is larger then the height but you set the frame at a different aspect ratio you will see a white space above and below the image.
But there were other problems too. You need to clip an image with the .clipped() modifier after you set its frame, else it will overflow the frame. Why all those ZStacks? I cannot see any purpose of adding a ZStack with only one child.
BUT:
As your code is not reproducible i had to add or remove several things to make it work. So you need to adopt this to your code.
Solution:
struct ContentView: View{
#State private var products: [ProductData] = [ProductData(product_name: "test", product_details: "test"), ProductData(product_name: "test2", product_details: "test2"), ProductData(product_name: "test3", product_details: "test3")]
#State private var show = false
#State private var selectedProduct: ProductData?
var body: some View{
ScrollView(.vertical, showsIndicators: false, content: {
Spacer()
LazyVGrid(columns: Array(repeating: GridItem(.flexible(),spacing: 15), count: 2),spacing: 10){
ForEach(products){product in
// Product View...
ProductView(productData: product)
.background(.white)
.clipShape(RoundedRectangle(cornerRadius: 15, style: .continuous))
.shadow(color: .black.opacity(0.4), radius: 3, x: 1, y: 1)
.onTapGesture {
withAnimation(.easeIn){
selectedProduct = product
show.toggle()
}
}
}
}
Spacer()
.padding()
.padding(.top,10)
})
.padding(.top, 20)
}
}
struct ProductData: Identifiable{
var id = UUID()
var product_name: String
var product_details: String
}
struct ProductView: View{
var productData: ProductData
var body: some View{
VStack(alignment: .center, spacing: 0) {
Image("test")
.resizable()
.aspectRatio(contentMode: .fill)
.frame(width: 160, height: 225)
.cornerRadius(15)
.clipped()
.padding(5)
Text(productData.product_name)
.font(.title2)
.fontWeight(.bold)
.foregroundColor(.black)
.padding()
Text(productData.product_details)
.font(.caption)
.foregroundColor(.gray)
.lineLimit(2)
.padding()
}
}
}
Outcome:

The logic of clicking like in SwiftUI

world! I want to make sure that the like is placed only on one card, and not on all at once. I wrote the logic of painting the like and clicking it. But this applies to all cards, not just the one where I clicked like.
How can I change the logic so that the like is placed only on the card I clicked on?
Below the code CellView() is a cell with a card, which I then use in another view
struct CellView: View{
//MARK: - PROPERTIES
#AppStorage("isLiked") var isLiked: Bool = false
var data: Model
//MARK: - BODY
var body: some View{
VStack{
VStack{
AnimatedImage(url: URL(string: data.photo)!)
.resizable()
.aspectRatio(contentMode: .fit)
.overlay(RoundedRectangle(cornerRadius: 10).stroke(Color("GrayWhite"), lineWidth: 0.5)
)
}.background(Color.white)
.cornerRadius(10)
VStack{
HStack{
Text("\(data.price) ₽")
.font(.system(size: 16, weight: .bold))
.foregroundColor(Color("BlackWhite"))
Spacer()
Button(action: {
self.isLiked.toggle()
}, label: {
Image(systemName: isLiked ? "heart.fill" : "heart")
.frame(width: 22, height: 22)
.foregroundColor(isLiked ? .red : .black)
})
}.padding(.bottom, 1)
HStack{
Text(data.company)
.font(.system(size: 14, weight: .bold))
.lineLimit(1)
.foregroundColor(Color("BlackWhite"))
Spacer()
}
HStack{
Text(data.name)
.font(.system(size: 14, weight: .bold))
.lineLimit(1)
.foregroundColor(.gray)
Spacer()
}
}
.padding(.horizontal, 2)
}
.padding(5)
}
}
Thank you in advance for your help
Each cell has to be identified for Swift to know what is liked.
import SwiftUI
struct CardData: Identifiable {
var id: String = UUID().uuidString
// add the rest of the data associated with the cards, company, etc.
}
And if we want to follow the MVVM-structure you create a separate file for the functions (when we check like and unlike each card).
class CellViewModel: ObservableObject {
#Published var card: CardData!
#Published var isLiked = false
func like() {
isLiked.toggle()
}
}
Now all our CellViews can be liked seperately (I removed some your inputs, for test)
struct CellView: View{
//MARK: - PROPERTIES
#ObservedObject var cellViewModel: CellViewModel = CellViewModel()
init(cardData: CardData) {
self.cellViewModel.card = cardData
}
//MARK: - BODY
var body: some View{
VStack{
VStack{
Image(systemName: "circle")
.resizable()
.aspectRatio(contentMode: .fit)
.overlay(RoundedRectangle(cornerRadius: 10).stroke(Color("GrayWhite"), lineWidth: 0.5)
)
}.background(Color.white)
.cornerRadius(10)
VStack{
HStack{
Text(" ₽")
.font(.system(size: 16, weight: .bold))
.foregroundColor(Color("BlackWhite"))
Spacer()
Button(action: {
cellViewModel.like()
}, label: {
Image(systemName: cellViewModel.isLiked ? "heart.fill" : "heart")
.frame(width: 22, height: 22)
.foregroundColor(cellViewModel.isLiked ? .red : .black)
})
}.padding(.bottom, 1)
HStack{
Text("company")
.font(.system(size: 14, weight: .bold))
.lineLimit(1)
.foregroundColor(Color("BlackWhite"))
Spacer()
}
HStack{
Text("name")
.font(.system(size: 14, weight: .bold))
.lineLimit(1)
.foregroundColor(.gray)
Spacer()
}
}
.padding(.horizontal, 2)
}
.padding(5)
}
}
Testing liking seperately:
struct ContentView: View {
var body: some View {
VStack {
CellView(cardData: CardData())
CellView(cardData: CardData())
CellView(cardData: CardData())
CellView(cardData: CardData())
}
}
}

iOS: How to make my image logo at the top of the page SwiftUI

firstly I am really new to iOS development and Swift (2 weeks coming here from PHP :))
I am building my simple Login page and wondering how to make my Logo image at the top of the page. Also I am wondering if I have done my layout wrong to get the desired layout as in the screenshot. Would appreciate the help on this.
(Logo scribbled out in the screen shot needs to go to the top outside the white background)
Thanks
LoginView:
import SwiftUI
struct LoginView: View {
#State private var email: String = ""
#State private var password: String = ""
let verticalPaddingForForm = 40
var body: some View {
ZStack {
Color(red: 20/225.0 ,green: 22/225.0 , blue: 25/225.0)
VStack(spacing: CGFloat(verticalPaddingForForm)) {
Image("logo")
.resizable()
.scaledToFit()
Divider()
VStack {
TextField("Email", text: $email)
.padding(.horizontal, 30).padding(.top, 20)
Divider()
.padding(.horizontal, 30)
SecureField("Password", text: $password)
.padding(.horizontal, 30).padding(.top, 20)
Divider()
.padding(.horizontal, 30)
}
.background(Color(.white))
Text("Forgotten Password")
.foregroundColor(.blue)
.font(.system(size: 15))
Button(action: /*#START_MENU_TOKEN#*/{}/*#END_MENU_TOKEN#*/) {
Text("Login")
.padding()
.font(.system(size: 20))
}
.background(Color.black)
.foregroundColor(Color.white)
.cornerRadius(10)
.padding(.top, 0)
.padding(.bottom, 20)
}
.padding(.horizontal, CGFloat(verticalPaddingForForm))
.background(Color(.white))
VStack{
Spacer()
Button(action: /*#START_MENU_TOKEN#*/{}/*#END_MENU_TOKEN#*/) {
Text("Register")
.padding()
.font(.system(size: 40))
}
.background(Color(red: 20/225.0 ,green: 22/225.0 , blue: 25/225.0))
.foregroundColor(Color.white)
.cornerRadius(10)
.padding()
}
}.ignoresSafeArea()
};
}
ContentView:
import SwiftUI
struct ContentView: View {
var body: some View {
LoginView()
}
}
extension UIDevice {
var hasNotch: Bool {
let bottom = UIApplication.shared.keyWindow?.safeAreaInsets.bottom ?? 0
return bottom > 0
}
}
Try below code-:
Use a ZStack to give a backgroundColor to your view, and give that a modifier of .ignoresSafeArea().
Use VStack inside ZStack to layout other view components. I have done few modifications on my side.
struct LoginView: View {
#State private var email: String = ""
#State private var password: String = ""
let verticalPaddingForForm = 40
var body: some View {
ZStack() {
Color(red: 20/225.0 ,green: 22/225.0 , blue: 25/225.0).ignoresSafeArea()
VStack(spacing:15){
Image(systemName: “logo")
.resizable()
.scaledToFit()
.frame( height: 200)
.foregroundColor(Color.white)
.padding([.top],15)
VStack(spacing: CGFloat(verticalPaddingForForm)) {
VStack {
TextField("Email", text: $email)
.padding(.horizontal, 30).padding(.top, 20)
Divider()
.padding(.horizontal, 30)
SecureField("Password", text: $password)
.padding(.horizontal, 30).padding(.top, 20)
Divider()
.padding(.horizontal, 30)
}
.background(Color(.white))
.padding([.top])
Text("Forgotten Password")
.foregroundColor(.blue)
.font(.system(size: 15))
Button(action: {}) {
Text("Login")
.padding()
.font(.system(size: 20))
}
.background(Color.black)
.foregroundColor(Color.white)
.cornerRadius(10)
.padding([.bottom])
}
.background(Color(.white))
Spacer()
Button(action: {}) {
Text("Register")
.padding()
.font(.system(size: 40))
}
.foregroundColor(Color.white)
.cornerRadius(10)
}
}
};
}
struct Test1: View {
var body: some View {
LoginView()
}
}
extension UIDevice {
var hasNotch: Bool {
let bottom = UIApplication.shared.keyWindow?.safeAreaInsets.bottom ?? 0
return bottom > 0
}
}
You can use ZStack (alignment: .top) to set the alignment from the top. And then you can use a Spacer() at the end of the second VStack to expand the view.
The following code works for me. It's your code with little changes. Also, I suggest you create a subview to better organize your code, instead of writing all views within the same view.
import SwiftUI
struct LoginView: View {
#State private var email: String = ""
#State private var password: String = ""
let verticalPaddingForForm = 40
var body: some View {
ZStack (alignment: .top){
Color(red: 20/225.0 ,green: 22/225.0 , blue: 25/225.0)
VStack(spacing: CGFloat(verticalPaddingForForm)) {
Image(systemName: "gear")
.resizable()
.scaledToFit()
.frame(width: 100)
Divider()
VStack {
TextField("Email", text: $email)
.padding(.horizontal, 30).padding(.top, 20)
Divider()
.padding(.horizontal, 30)
SecureField("Password", text: $password)
.padding(.horizontal, 30).padding(.top, 20)
Divider()
.padding(.horizontal, 30)
}
.background(Color(.white))
Text("Forgotten Password")
.foregroundColor(.blue)
.font(.system(size: 15))
Button(action: /*#START_MENU_TOKEN#*/{}/*#END_MENU_TOKEN#*/) {
Text("Login")
.padding()
.font(.system(size: 20))
}
.background(Color.black)
.foregroundColor(Color.white)
.cornerRadius(10)
.padding(.top, 0)
.padding(.bottom, 20)
Spacer()
}
.padding(.horizontal, CGFloat(verticalPaddingForForm))
.background(Color(.white))
VStack{
Spacer()
Button(action: /*#START_MENU_TOKEN#*/{}/*#END_MENU_TOKEN#*/) {
Text("Register")
.padding()
.font(.system(size: 40))
}
.background(Color(red: 20/225.0 ,green: 22/225.0 , blue: 25/225.0))
.foregroundColor(Color.white)
.cornerRadius(10)
.padding()
}
}
}
}
struct LoginView_Previews: PreviewProvider {
static var previews: some View {
LoginView()
}
}
Just put Spacer() between Image("logo") and Divider() to push your logo to the top of the screen

SwiftUI Button not being tapped

I Have a button embedded inside a Hstack inside a Vstack inside a ZStack inside a Vstack inside a geometryReader in swiftui that does not get tapped. I put a print statement inside and whenever I tried to Tap the button, the print statement won't print. Can anyone help me out here? Thanks. Heres my code:
struct DetailedGroupView: View {
#State var actrualImage: Image?
#State var title = "title"
#State var description = "description"
#State var sgName = "sgName"
#State var membersCount = 0
#Environment(\.presentationMode) var presentationMode
var body: some View {
GeometryReader{ geo in
VStack{
ZStack{
(self.actrualImage ?? Image("earthPlaceholder"))
.resizable()
.aspectRatio(contentMode: .fill)
VStack{
Spacer()
HStack{
//This button doesn't work
Button(action: {
print("Button Tapped")
self.presentationMode.wrappedValue.dismiss()
}, label: {
Image(systemName: "chevron.left").foregroundColor(.white)
}).padding()
Text(self.title)
.font(.largeTitle)
.fontWeight(.bold)
.multilineTextAlignment(.leading)
.foregroundColor(.white)
.padding()
.minimumScaleFactor(0.5)
Spacer()
}
HStack{
Text(self.description)
.font(.custom("Open Sans", size: 18))
.fontWeight(.ultraLight)
.multilineTextAlignment(.leading)
.foregroundColor(.white)
.padding()
Spacer()
}
Spacer()
HStack{
Image(systemName: "person.2.fill").foregroundColor(.white).padding(.leading)
Text("\(self.membersCount)")
.font(.custom("Open Sans", size: 12))
.fontWeight(.semibold)
.foregroundColor(.white)
Spacer()
Text(self.sgName)
.font(.custom("Open Sans", size: 12))
.fontWeight(.semibold)
.foregroundColor(.white)
.padding()
}.padding()
}.frame(width: geo.size.width, height: 294)
}.frame(width: geo.size.width, height: 294)
.clipShape(RoundedRectangle(cornerRadius: 12))
.edgesIgnoringSafeArea(.top)
Spacer()
ScrollView(showsIndicators: false){
VStack{
Spacer()
}.onAppear{
self.actrualImage = Image("globePlaceholder")
}
}
}
}.navigationBarBackButtonHidden(true)
}
}
Just tested this same code on both XCode 11.5 and 12.0, and the button works fine... be sure to test it on a simulator not on the preview/canvas

How would I create the visual equivalent of a UIView in SwiftUI?

Here is my code for my List items in my project using SwiftUI.
struct ServicesListItem: View {
var title: String
var description: String
var colorHex: String
var imageName: String
var body: some View {
HStack {
Image(imageName)
.resizable()
.aspectRatio(contentMode: .fit)
.frame(width: 50, height: 50)
VStack(alignment: .leading, spacing: 4) {
Text(title)
.font(.system(size: 14, weight: .black, design: .rounded))
.foregroundColor(Color(hex: colorHex))
Text(description)
.font(.system(size: 10, weight: .medium, design: .rounded))
.foregroundColor(Color.gray)
}
.frame(height: 60)
}
}
}
I want to put all of the elements of each ServicesListItem inside another "view" and add padding on all sides to give the appearance that the contents of each item are inside a raised view rather than the edge-to-edge look of the List. I've done this easily with UIKit by using a UIView as a parent view inside of a UITableViewCell. haven't found a means of doing this yet with SwiftUI. Is it possible?
SwiftUI 1.0
Hi Austin, here are a couple of relevant changes I made to your list item view:
Moved the frame to the HStack level
Made HStack fill width of device with .maxWidth: .infinity
Added a solid background color that you can then add a shadow to for the "raised look"
Code
struct ServicesListItem: View {
var title: String
var description: String
var colorHex: String
var imageName: String
var body: some View {
HStack {
Image(imageName)
.resizable()
.aspectRatio(contentMode: .fit)
.frame(width: 50, height: 50)
VStack(alignment: .leading, spacing: 4) {
Text(title)
.font(.system(size: 14, weight: .black, design: .rounded))
.foregroundColor(Color(hex: colorHex))
Text(description)
.font(.system(size: 10, weight: .medium, design: .rounded))
.foregroundColor(Color.gray)
}
}
// Set the size of entire row. maxWidth makes it take up whole width of device.
.frame(maxWidth: .infinity, maxHeight: 60, alignment: .leading)
.padding(10) // Spacing around all the contents
// Add a solid colored background that you can put a shadow on
// (corner radius optional)
.background(Color.white.cornerRadius(5).shadow(radius: 3))
}
}
Example
Is this similar to what you were thinking?
(As of SwiftUI 1.0, we don't know how to remove the lines. ☹️)

Resources