SwiftUI changing the color of clear part inside of SF Symbol - swift

I am trying to change the color of clear(transparent) part inside of a SF Symbol called delete.left.fill. So far I've tried is as follows
Button(action: { return }, label: {
Image(systemName: "delete.left.fill")
.background(Color.black)
//.accentColor(.black)
.font(.system(size: self.fontSize*0.75))
})
.frame(width: self.width, height: self.width)
.foregroundColor(.lightGray)
//.background(Color.black)
When I run the code as above, the result is like
.
At first, the xinside of the symbol was the same color as background. I want it to make black.
I tried to set the backgroundColor of the Button and it made
whole Button black.
I tried to set accentColor of the Image to
black. Nothing changed.
I tried to set backgroundColor of the
Image to black. The result can be seen in the image.
The question is, is there a way to make just that x, inside the symbol, black programmatically?

You could mask the background and apply a custom style:
struct MyButtonStyle: ButtonStyle {
public func makeBody(configuration: MyButtonStyle.Configuration) -> some View {
configuration.label
.compositingGroup()
.opacity(configuration.isPressed ? 0.5 : 1.0)
}
}
Button(action: {}) {
Image(systemName: "delete.left.fill")
.foregroundColor(.green)
.background(
Color.black.mask(Circle())
)
}.buttonStyle(MyButtonStyle())
The circle may not fit to any usage, but for this image it works okay:

As he warned with the circle, #Faruk's solution didn't work for me with the exclamationmark.triangle.fill
I created a ZStack with the fill and unfill versions to create a yellow triangle with a black exclamation point and a black border:
ZStack{
Image(systemName: "exclamationmark.triangle")
.foregroundColor(Color.black)
.scaleEffect(1.1)
Image(systemName: "exclamationmark.triangle.fill")
.foregroundColor(Color.yellow)
}
I've only tried on couple of simulators, but it looks nice on iPadPro and iPad Mini

as of iOS 15 you can simply achieve that with .foregroundStyle(.red, .blue)

Related

Button Corner to round button (Xcode,Swift) [duplicate]

With UIKit, it's possible to give a control (e.g. a button) perfectly rounded corners (resulting in a circle on each side) by using this approach:
exampleButton.cornerRadius = exampleButton.frame.size.height/2
How does one achieve the same result with a SwiftUI view?
Because the views are defined more on the fly, I'm not sure how it would be possible to reference that frame size unless it's being set manually (which isn't the desire here).
Button(action: {
// ...
}) {
Text("I'm a Button")
}
.cornerRadius(???)
Another solution to this is to use shapes, in this case the Capsule shape, and use the clipShape modifier
Taking the example already mentioned, it would be like this:
Button(action: {
// ...
}) {
Text("I'm a Button")
.padding(.horizontal, 10)
.background(Color.red)
.clipShape(Capsule())
}
The padding in there can be adjusted so that your view looks how you want it to. The point it that capsule will always have the ends perfectly rounded. In this case I didn't want the text to be too close to the rounded edges, so I applied some padding to the sides.
A note to remember is that in SwiftUI the order the modifiers are applied in is very important.
You need to define it as a square and then put rounding on corners, like this:
Button(action: {
// ...
}) {
Text("I'm a Button")
.frame(width:150, height:150)
.background(Color.red)
.cornerRadius(.infinity)
}
PS. Added some background color for visibility
Working in XCode 12.4
For anyone who found this question trying to find out how to make a button with rounded corners (whether completely round like a capsule or not):
Button(action: {
// Do whatever
}) {
Spacer()
Text("Log In")
.font(.title2)
.padding()
.foregroundColor(.white)
Spacer()
}
.background(Color(UIColor.systemBlue))
.clipShape(RoundedRectangle(cornerRadius: 12))
.padding()
No need to fuss around with overlay shapes.
Another solution is to use geometry reader which will take the height or width of the screen and allow you to divide, multiply subtract or add from it.
Using the example, it would be like this:
GeometryReader { Geometry in
Button(action: {
// ...
}) {
Text("I'm a Button")
}
.cornerRadius(geometry.size.width / 2)
}
It is the most similar to frame.size.height.

How to set the opacity of an overlay in SwiftUI

I'm trying to set the opacity of an overlay in SwiftUI.
However, I'm only trying to change the opacity of the overlay, and want to keep the opacity of the symbol that is being overlayed. But, when i apply the .opacity() modifier, it changes the opacity of the whole view (both the image and the overlay)
Image(systemName: "magnifyingglass")
.resizable()
.aspectRatio(contentMode: .fit)
.frame(width: 20, height: 20)
.padding(10)
.overlay(Color.gray)
.opacity(0.1)
.clipShape(Circle())
this code produces this view.
as you can see, the entire view is barely visible, and I am trying to only make the gray circle around the search icon opaque, and keep the opacity of the search icon itself.
You're adding opacity to your whole view, add it to your overlay instead:
.overlay(Color.gray.opacity(0.1))
Why are you overlaying the gray circle on top of the symbol? Shouldn't it be the other way around? The order of view modifiers, including .opacity(), are very important in SwiftUI. If you want to only adjust the opacity of the gray circle, you must attach .opacity() before the overlay.
Color.gray
.frame(width: 40, height: 40)
.clipShape(Circle())
.opacity(0.1) /// apply to the gray circle
.overlay( /// overlay does not get affected
Image(systemName: "magnifyingglass")
.resizable()
.aspectRatio(contentMode: .fit)
.padding(10)
)
Result:

Round Specific Corners of Stroke/Border SwiftUI

I am working on a SwiftUI project where I need a view to have a border with only some of the corners rounded (for instance, the top left and top right).
I added a RoundedRectangle with a stroke and was able to have all of the corners rounded. However, I need only some of the corners to be rounded and I couldn't figure out a way to do that.
This is the code I had to add a RoundedRectangle:
.overlay(
RoundedRectangle(cornerRadius: 20)
.stroke(Color.gray, lineWidth: 1)
)
To make only specific corners rounded, I looked at this Stackoverflow post: Round Specific Corners SwiftUI. However, I would have to get rid of the Rounded Rectangle (because it rounds all corners). I would have to use a normal border instead. But, with a normal border, it will cut out a piece of the border when rounding corners and trying any of the answers provided.
This is what I would ideally want it to look like (this is from an example from Bootstrap - we are rebuilding a website as an app):
Thank you!
Here's an alternative / easier way to recreate this. Add a white background to each of the rows and add a single gray background color behind them. Add spacing between the rows to let the gray background color appear like a divider between them. Then just add a rectangle overlay to the entire view, like you already had in your code!
struct CornerView: View {
var body: some View {
VStack(spacing: 1) {
ForEach(0..<5) { index in
Text("Item \(index)")
.frame(maxWidth: .infinity)
.frame(height: 55)
.background(Color.white)
}
}
.background(Color.gray)
.overlay(
RoundedRectangle(cornerRadius: 5)
.stroke(Color.gray, lineWidth: 1)
)
.padding()
}
}
struct CornerView_Previews: PreviewProvider {
static var previews: some View {
CornerView2()
}
}

How to get rid of the blue selection border around SwiftUI TextFields?

I have created two textfields with the following code:
VStack (spacing: geometry.size.width/48) {
TextField("World Name", text: self.$WorldName)
.font(.system(size: geometry.size.width/28))
.textFieldStyle(PlainTextFieldStyle())
.frame(width: geometry.size.width*0.75)
.background(
RoundedRectangle(cornerRadius: 8)
.fill(Color.init(white: 0.28))
)
TextField("World Seed", text: self.$WorldSeed)
.font(.system(size: geometry.size.width/28))
.textFieldStyle(PlainTextFieldStyle())
.frame(width: geometry.size.width*0.75)
.background(
RoundedRectangle(cornerRadius: 8)
.fill(Color.init(white: 0.28))
)
Button (action: {
withAnimation {
self.back.toggle()
}
// Is there a way to "deselect" any textfields here
}){
Text("Back")
}
}
Why is it when I click on one, there is a blue border that does not fade out with the animation, and how can I remove it? This question is specific, and I have provided code, and necessary details, I don't see why it should be too hard to answer.
So in summarized terms, I need to know:
How to get rid of this blue selection border
Or
How to immediately deselect the text field within the button's action,
Get the border to properly line up with the TextField if I apply a padding or round corners.
The only blue in this picture is the border I am referring to
As shown in this screenshot, the textfield is round, but the selection border does not get round corners to reflect the rounded rectangle shape of the entry
The blue border does not fit the padding
I added a padding like this .padding([.leading, .trailing], 6)
You can remove the blue border (which appears on macos even when using PlainTextFieldStyle) by extending NSTextField like so:
extension NSTextField {
open override var focusRingType: NSFocusRingType {
get { .none }
set { }
}
}
See Apple Developer Forum answer here
I don't know which blue border are you referring to, if you are referring to blue border for textfield, there is no blue border beacuse you have given a PlainTextFieldStyle
To deselect the textfield
UIApplication.shared.windows.filter({$0.isKeyWindow}).first?.endEditing(true)
To have a rounded textfield with padding
ZStack {
Rectangle()
.foregroundColor(.clear)
.overlay(RoundedRectangle(cornerRadius: 6).stroke(Color("appcolor").opacity(0.5), lineWidth: 1))
TextField("Enter some text", text: $worldName)
.padding([.leading, .trailing], 6)
}.frame(height: 42)
.padding([.leading, .trailing], 10)

SwiftUI: Increase tap/drag area for user interaction

I've built a custom slider in SwiftUI with a thumb dragger that is 20x20. Everything is working, except the tap target is quite small since it's just the 20x20 view. I'm looking for a way to increase this to make it easier for users to interact with my slider. Is there a way to do this in SwiftUI?
I tried wrapping my thumb in Color.clear.overlay and setting the frame to 60x60. This works if the color is solid, like red, but with clear the tap target seems to revert back to visible pixels of 20x20.
You can see on this gif I'm able to drag the slider even when clicking outside of the thumb.
However, as soon as I change the color to clear, this area no longer receives interactions.
Add a .contentShape(Rectangle()) after the frame.
I'm sure there are several ways to accomplish this, but this is how i made a big button with the whole area tappable:
Button(action: { someAction() }, label: {
Text("OK")
.frame(minWidth: 200)
.contentShape(Rectangle())
.padding()
})
.background(Color.blue)
.foregroundColor(.white)
.cornerRadius(5.0)
I had the same problem. Except I didn't want the expanded overlay to impact the rest of the layout. If you embed everything in a ZStack and put a rectangle before your interactive object, you can control the size of the gesture. Kind of like this:
Rectangle().frame(width: screen.width, height: 300).opacity(0.001)
.layoutPriority(-1)
Just needed to make sure to set the opacity to next to nothing so you can't see it, and the layout priority to -1 so it doesn't impact the view.
As a follow up to the answer above, You can enlarge the clickable rect all day using this as example.
ZStack {
Image(systemName: secured ? "eye.slash" : "eye")
.resizable()
.renderingMode(.template)
.aspectRatio(contentMode: .fit)
.frame(width: 16, height: 16)
Rectangle()
.frame(width: 22, height: 20)
.opacity(0.001)
.onTapGesture {
self.secured.toggle()
}
}