I have a list that produces card views with a ForEach. They are meant to have a clear background, but one of them always has a white background and I can't figure out how to change it. I have tried putting .background(Color.clear) on any view I can think of, as well as using .listRowBackground(Color.clear), but one view will still have a background despite the fact that it is the same as all of the others.
Here's an image to show what I am talking about:
And here is the code for the body of the navigationView that these are presented in:
NavigationView{
List{
//loop through task cards
ForEach(self.tasks, id: \.id) { task in
//show task card
task
.listRowBackground(Color.clear)
.background(Color.clear)
}
.listRowBackground(Color.clear)
.listStyle(SidebarListStyle())
.environment(\.defaultMinListRowHeight, 120).padding(0.0)
//LIST end
}
.listStyle(SidebarListStyle())
.environment(\.defaultMinListRowHeight, 120).padding(0.0)
.background(Color.clear)
//NAVIGATION VIEW end
}.background(Color.clear)
.stackOnlyNavigationView()
and here is the code for the body of the views that appear in the ForEach above (called "task"):
GeometryReader{ geo in
RoundedRectangle(cornerRadius: 10)
.foregroundColor(Color.lightAccent)
.background(Color.clear)
.frame(height: self.height)
.overlay(
HStack{
//blah blah blah probably not important to the issue
//if it is let me know and I will edit
//HSTACK
}.frame(width: geo.size.width, height: self.height)
.cornerRadius(10)
.overlay(
RoundedRectangle(cornerRadius: 10)
.stroke((self.id == self.selectionManager.id) ? Color.blue : Color.mid, lineWidth: (self.id == self.selectionManager.id) ? 3 : 1))
.background(Color.clear)
.foregroundColor(Color.clear)
//OVERLAY end
)
}
Try to use .clipShape, but it is hard to say exact place w/o having your code...
GeometryReader{ geo in
RoundedRectangle(cornerRadius: 10)
.foregroundColor(Color.lightAccent)
.background(Color.clear)
.frame(height: self.height)
.overlay(
HStack{
//blah blah blah probably not important to the issue
//if it is let me know and I will edit
//HSTACK
}.frame(width: geo.size.width, height: self.height)
.cornerRadius(10)
.overlay(
RoundedRectangle(cornerRadius: 10)
.stroke((self.id == self.selectionManager.id) ? Color.blue : Color.mid, lineWidth: (self.id == self.selectionManager.id) ? 3 : 1))
.background(Color.clear)
.foregroundColor(Color.clear)
//OVERLAY end
)
.clipShape(RoundedRectangle(cornerRadius: 10)) // << here !!
}
.clipShape(RoundedRectangle(cornerRadius: 10)) // << or here !!
Related
I am new to SwiftUI and trying to play around with some stuff.
I want to have a ZStack so I can have a background color with a see through black color that should animate on the opacity. On top of that I want to animate a "card view" in from the bottom. This is not possible currently with the code I have managed to use. Both background color and the card view is animating on the opacity - from invisible to visible.
How do I animate these two items inside the ZStack with a different transition?
Here is what I have done so far but without the correct result:
ZStack {
Color.black
.ignoresSafeArea()
.opacity(animateSmileys ? 0.3 : 0)
.animation(.easeInOut)
.zIndex(0)
VStack {
Spacer()
VStack(spacing: 30) {
Text("Hvordan har du det i dag?")
.font(.title2)
.fontWeight(.heavy)
.foregroundColor(Color("playerTopView"))
HStack {
ForEach(Array(moods.enumerated()), id: \.offset) { index, mood in
SmileyView(bgColor: mood.bgColor, smileyName: mood.smileyName)
.aspectRatio(contentMode: .fit)
.scaleEffect(CGFloat(animateSmileys ? 1 : 0), anchor: .center)
.rotationEffect(.degrees(animateSmileys ? 0 : 180), anchor: .center)
.animation(.interpolatingSpring(stiffness: 150, damping: 10).speed(2).delay(Double(index) * 0.2), value: animateSmileys)
}
}
HStack {
Spacer()
}
}
.padding()
.padding(.top, 20)
.background(Color("backgroundColor"))
.clipShape(RoundedRectangle(cornerRadius: 30, style: .continuous))
.shadow(radius: 20)
}
.padding()
.transition(.move(edge: .bottom))
.animation(.spring())
.onAppear {
animateSmileys = true
}
.zIndex(1)
}
Hope you guys can help me!
I tried the above code and moving the .transition(.move(edge: .bottom)) and .animation(.spring()) from the VStack holding the "card view" to the VStack inside the VStack.
I don't want the behavior I'm getting with this SwiftUI thing (first time messing with it). I've been putting .background() on everything and there's some kind of padding happening and some sort of dividing line, whether I enable the Button code or not (pic below is with Button code commented out).
What do I need to do to fix it?
var body: some View {
ZStack() {
Color.black
.ignoresSafeArea(.all)
VStack(alignment: .leading, spacing: 0) {
List(eventFields) { eventField in
HStack() {
Spacer(minLength: 10)
if let iconName = eventField.iconName {
Button(action: {
print("edit \(eventField.name)")
}, label: {
Image(uiImage: UIImage(named: iconName)!.colorizeMask(eventField.iconColor!))
.frame(width: 27, height: 27)
self.background(.black)
}).background(.black)
} else {
Text("")
.frame(width: 27)
}
Text(eventField.iconName == nil ? "" : eventField.name)
.font(.system(size: eventField.labelFontSize))
.foregroundColor(eventField.labelFontColor)
.frame(width: 50, alignment: .trailing)
Spacer(minLength: 3)
Text(eventField.stringValue)
.font(.system(size: eventField.fontSize))
.foregroundColor(eventField.fontColor)
.frame(width: 200, alignment: .leading)
Spacer(minLength: 10)
}.background(.black)
}.background(.black)
}
}
}
}
instead of putting .background on the HStack, use
.listRowBackground(Color.black)
and for separator use
.listRowSeparator(.hidden)
Keep in mind, this is on the HStack not the List
Full Code:
var body: some View {
ZStack() {
Color.black
.ignoresSafeArea(.all)
VStack(alignment: .leading, spacing: 0) {
List(eventFields) { eventField in
HStack() {
Spacer(minLength: 10)
if let iconName = eventField.iconName {
Button(action: {
print("edit \(eventField.name)")
}, label: {
Image(uiImage: UIImage(named: iconName)!.colorizeMask(eventField.iconColor!))
.frame(width: 27, height: 27)
self.background(.black)
}).background(.black)
} else {
Text("")
.frame(width: 27)
}
Text(eventField.iconName == nil ? "" : eventField.name)
.font(.system(size: eventField.labelFontSize))
.foregroundColor(eventField.labelFontColor)
.frame(width: 50, alignment: .trailing)
Spacer(minLength: 3)
Text(eventField.stringValue)
.font(.system(size: eventField.fontSize))
.foregroundColor(eventField.fontColor)
.frame(width: 200, alignment: .leading)
Spacer(minLength: 10)
}
.listRowBackground(Color.black)
.listRowSeparator(.hidden)
}
}
}
}
}
I believe the color specification for your hstack and frames is supposed to be "(Color.black)" instead of just "(.black)".
Which type of color you use isn't consistent across all Swift objects. Some objects, such as UITableView use "UI colors" which are in the form ".black", while others, like frames, vstacks, hstacks and other objects, use SwiftUI colors in the form "Color.black".
I recommend this very informative page for a very accessible explanation of using color in a view and a stack.
Good day, beginner SwiftUI & iOS developer here.
I'm not quite sure how else I could've worded this question, but I'll try my best to explain what I would like to achieve.
Right now, I have a VStack that contains a WebImage and Text view, and this VStack is nested inside a HStack. The views inside the VStack are inside a ForEach loop and are generated dynamically with the data I fetch.
When I display these on a screen, all of these views appear in a single line, as shown below.
However I would like for there to only be max two views per "line", not all four of them stacked into a single line. Is there a way to achieve this?
Here is the code:
HStack(spacing: 20) {
ForEach(attViewModel.students, id: \.self) { student in
VStack {
WebImage(url: URL(string: student.photo))
.resizable()
.aspectRatio(contentMode: .fill)
.frame(width: 40, height: 40)
.clipShape(Circle())
.overlay(Circle().stroke(Color("DarkGreen"), lineWidth: 3))
.compositingGroup()
Text("\(student.name)")
.bold()
.compositingGroup()
CustomRadioButton()
}
.padding()
.overlay(RoundedRectangle(cornerRadius: 10)
.stroke(Color.orange, lineWidth: 2))
.shadow(radius: 7)
}
}
.frame(maxWidth: .infinity)
Here a possible approach for you:
struct ContentView: View {
let arrayOfStudents: [String] = ["jessy", "joy", "joly", "jack"]
var body: some View {
GeometryReader { proxy in
ScrollView(.horizontal) {
HStack(spacing: .zero) {
ForEach(arrayOfStudents, id: \.self) { student in
VStack {
Image(systemName: "person")
.resizable()
.aspectRatio(contentMode: .fit)
.frame(width: 40, height: 40)
.padding()
.clipShape(Circle())
.overlay(Circle().stroke(Color.green, lineWidth: 3))
Text(student)
.bold()
Circle()
.strokeBorder(style: .init(lineWidth: 2))
.frame(width: 10, height: 10)
}
.compositingGroup()
.padding()
.overlay(RoundedRectangle(cornerRadius: 10).stroke(Color.orange, lineWidth: 2))
.shadow(radius: 7)
.padding()
.frame(width: proxy.size.width/2.0)
}
}
}
.position(x: proxy.size.width/2.0, y: proxy.size.height/2.0)
}
}
}
Is there a way using SwiftUI to get a two row NavigationBar like instagram has? Even better would be two rows with a fullwidth search bar like in the image.
ex.
Here you go an example close to the image, of course it can be redesigned to suit your needs I did it very quickly it doesn't look nice, but as I said it can be redesigned to look much nicer:
#State var testok = ""
var body: some View {
VStack {
VStack {
TextField("search here man", text: $testok)
.frame(maxWidth: .infinity)
.frame(height: 40)
.background(Color.red)
.cornerRadius(10)
.padding()
ScrollView(.horizontal){
HStack(spacing: 0) {
Text("ok")
.frame(width: 80, height: 50)
.background(Color.green)
.cornerRadius(8)
.padding(.horizontal, 10)
Text("yumyum")
.frame(width: 80, height: 50)
.background(Color.green)
.cornerRadius(8)
.padding(.horizontal, 10)
Text("lool")
.frame(width: 80, height: 50)
.background(Color.green)
.cornerRadius(8)
.padding(.horizontal, 10)
Text("pewpew")
.frame(width: 80, height: 50)
.background(Color.green)
.cornerRadius(8)
.padding(.horizontal, 10)
}
}
}
NavigationView {
NavigationLink(destination: Text("ok")) {
Text("ok")
.navigationTitle(Text("navigation title"))
}
}
}
}
I cannot figure out what compositingGroup() is. At first, I thought it is something like Merging layers in Photoshop. But it was not. Because .shadow() effects to the overlay and background views respectively even if I use .compositingGroup().
So far, I've found 2 differences when I use .compositingGroup()
Text doesn't have shadows.
The shadow size of the overlay view is slightly smaller than the above one.
What is the purpose of compositingGroup?
struct ContentView: View {
var body: some View {
VStack(spacing: 50) {
Text("Without\ncompositing")
.font(.largeTitle)
.bold()
.padding()
.foregroundColor(Color.white)
.background(RoundedRectangle(cornerRadius: 30).fill(Color.red))
.padding()
.padding()
.overlay(RoundedRectangle(cornerRadius: 30).stroke(lineWidth: 10))
.shadow(color: .blue, radius: 5)
Text("With\ncompositing")
.font(.largeTitle)
.bold()
.padding()
.foregroundColor(Color.white)
.background(RoundedRectangle(cornerRadius: 30).fill(Color.red))
.padding()
.padding()
.overlay(RoundedRectangle(cornerRadius: 30).stroke(lineWidth: 10))
.compositingGroup() // <--- I added .compositingGroup() here.
.shadow(color: .blue, radius: 5)
}
}
}
This modifier makes the following modifiers be applied to the view as a whole and not to each particular subview separately
Here's an example to better illustrate this:
struct ContentView: View {
let circles: some View = ZStack {
Circle()
.frame(width: 100, height: 100)
.foregroundColor(.red)
.offset(y: -25)
Circle()
.frame(width: 100, height: 100)
.foregroundColor(.blue)
.offset(x: -25, y: 25)
Circle()
.frame(width: 100, height: 100)
.foregroundColor(.green)
.offset(x: 25, y: 25)
}
var body: some View {
VStack(spacing: 100) {
circles
circles
.opacity(0.5)
circles
.compositingGroup()
.opacity(0.5)
}
}
}
So in your case the shadow is applied to the whole view rather than separately to the Text and overlaying RoundedRectangle
Use it when wanting to apply effects like opacity or shadow to a group of views and not each contained element by itself.
It seems like that .shadow() modifier will add both inner and outer shadow. It means that if the view is not "solid", for example, it has a "hole", .shadow() will add shadow like this:
RoundedRectangle(cornerRadius: 30)
.stroke(lineWidth: 10)
.frame(width: 300)
.shadow(color: .blue, radius: 5)
Click to see the image
So, if you do not want the inner shadow, you need to make your view be "solid", like this:
RoundedRectangle(cornerRadius: 30)
.stroke(lineWidth: 10)
.frame(width: 300)
.background(RoundedRectangle(cornerRadius: 30).fill(.white))
.shadow(color: .blue, radius: 5)
Click to see the image
However, something goes wrong again, the inner shadow doesn't disappear.
That's because I forgot to apply the .compositingGroup() modifier.
As #ramzesenok mentioned, .compositingGroup() makes the following modifiers be applied to the view as a whole and not to each particular subview separately.
So, change the code a little bit:
RoundedRectangle(cornerRadius: 30)
.stroke(lineWidth: 10)
.frame(width: 300)
.background(RoundedRectangle(cornerRadius: 30).fill(.white))
.compositingGroup()
.shadow(color: .blue, radius: 5)
Click to see the image
There is only outer shadow now.