Starting a new Mac App project from scratch and assigning Color.red and Color.green to two Rectangles results in the following:
Code:
struct ContentView: View {
var body: some View {
HStack {
Rectangle()
.frame(width: 200, height: 200)
.background(Color.green)
Spacer()
Rectangle()
.frame(width: 200, height: 200)
.background(Color.red)
}
}
}
#main
struct TestApp: App {
var body: some Scene {
WindowGroup {
ContentView()
}
}
}
Where do those very dark colors come from? How to have the interface use "normal" colors? I don't have dark mode activated and I'm on Big Sur.
You need to use fill or foregroundColor instead of background:
struct ContentView: View {
var body: some View {
HStack {
Rectangle()
.fill(Color.green) // first possibility: `fill`
.frame(width: 200, height: 200)
Spacer()
Rectangle()
.foregroundColor(Color.red) // second possibility: `foregroundColor`
.frame(width: 200, height: 200)
}
}
}
It's correct. To fill a shape use .fill(Color.green).
Related
Does anyone know how to make the following view in SwiftUI?
HStack:
[ blank logo(centered) Skip(text)]
So I have the following HStack:
Zstack(alignment: .topLeading) {
VStack{
HStack {
Image("onboarding-logo")
.resizable()
.scaledToFit()
.frame(width: 150.0, height: 150.0)
.padding(.top, 35)
}
}
}
Does anyone know how I can have a "Skip" text in the top right corner of the screen, but also keep my logo centered and not have anything on the left side? I've tried Spacers and all, but I'm having no luck.
I would like to click "Skip" and then lead to another view.
There are many ways to achieve this. Here I have used LazyVGrid since other answers based on Stacks
struct ContentView: View {
var body: some View {
VStack {
LazyVGrid(columns: [GridItem(), GridItem(), GridItem()], content: {
Spacer()
Image(systemName: "star.fill")
.frame(width: 150, height: 150, alignment: .center)
.border(.gray)
Button(action: {
}, label: {
Text("Skip")
})
})
.border(.gray)
Spacer()
}
}
}
Is this the screen configuration you want?
The Zstack is used to center the Hstack into which the image is placed, and the new HStack uses a spacer to move the Text to the right.
import SwiftUI
struct ContentView: View {
var body: some View {
ZStack {
VStack {
HStack(alignment: .center) {
Image("farnsworth")
.resizable()
.scaledToFit()
.frame(width: 150.0, height: 150.0)
}
Spacer()
}
VStack {
HStack {
Spacer()
Button {
// do Something...
} label: {
Text("Skip>>")
.padding(.top, 10)
}
}
Spacer()
}
}
.padding()
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
I want to use scaleEffect to scale a TextEditor contained in a VStack. When not scaled the text editor is very normal. But After scaling the editor can not be edited normally as the cursor can not be placed in the right place. Here is the code:
import SwiftUI
struct DemoTextView: View {
#State var text: String = ""
#State var scale: Double = 1
var body: some View {
VStack {
Spacer()
VStack {
TextEditor(text: $text)
.frame(width: 100, height: 100, alignment: .top)
.border(Color.red)
}
.scaleEffect(scale)
Spacer()
HStack {
Slider(value: $scale, in: 0.25...4)
Text("\(scale)")
}
.padding()
}
.frame(width: 500, height: 500, alignment: .center)
}
}
struct DemoTextView_Previews: PreviewProvider {
static var previews: some View {
DemoTextView()
}
}
And the screenshot of the wired behavior:
Anyone knows how to make the scaling of TextEditor works?
The default button style of ColorPicker is a circle as bellow.
I want to change the style of the circle button to Rectangle. But seems no API can change it style. So I put a Rectangle over it , and set it allowsHitTesting to false to transport click event to ColorPicker.
struct ColorPickerView: View {
#State private var colorValue = Color.orange
var body: some View {
ZStack() {
ColorPicker("", selection: $colorValue)
.labelsHidden()
Rectangle()
.foregroundColor(.blue)
.frame(width: 40, height: 40, alignment: .center)
.allowsHitTesting(false)
}
}
}
But the ColorPicker did not present after click.
I put a circle bellow the Rectangle to test whether allowsHitTesting is useful. It can work properly responding to tap gesture to print "Circle tapped!".
struct ColorPickerView: View {
#State private var colorValue = Color.orange
var body: some View {
ZStack() {
ColorPicker("", selection: $colorValue)
.labelsHidden()
Rectangle()
.foregroundColor(.blue)
.frame(width: 40, height: 40, alignment: .center)
.onTapGesture {
print("Circle tapped!")
}
Rectangle()
.foregroundColor(.blue)
.frame(width: 40, height: 40, alignment: .center)
.allowsHitTesting(false)
}
}
}
Why the ColorPicker can not responding to tap gesture? Or Is there a way to customize the ColorPicker button?
Simply use opacity, and send the ColorPicker to overlay, like in the code:
struct SquareColorPickerView: View {
#Binding var colorValue: Color
var body: some View {
colorValue
.frame(width: 40, height: 40, alignment: .center)
.cornerRadius(10.0)
.overlay(RoundedRectangle(cornerRadius: 10.0).stroke(Color.white, style: StrokeStyle(lineWidth: 5)))
.padding(10)
.background(AngularGradient(gradient: Gradient(colors: [.red,.yellow,.green,.blue,.purple,.pink]), center:.center).cornerRadius(20.0))
.overlay(ColorPicker("", selection: $colorValue).labelsHidden().opacity(0.015))
.shadow(radius: 5.0)
}
}
Use case:
struct ContentView: View {
#State private var colorValue = Color.orange
var body: some View {
SquareColorPickerView(colorValue: $colorValue)
}
}
I wanted to try this down code to see if SwiftUI understand between RoundedRectangle and Rectangle, therefore I ran this code, SwiftUI could tell me the difference between Screen Background tap and Rectangle tap, but it is unable to understand between RoundedRectangle itself and Background of RoundedRectangle which is a Rectangle.
How could I solve this issue?
Goal: I want get print for white area on tap, as well I am getting for red and yellow area.
struct ContentView: View {
var body: some View {
ZStack {
Color.red
.ignoresSafeArea()
.onTapGesture{ print("you tapped on Screen Background! 🟥") }
RoundedRectangle(cornerRadius: 90)
.fill(Color.yellow)
.frame(width: 300, height: 300, alignment: .center)
.background(Color.white.onTapGesture{ print("you tapped on RoundedRectangle Background! ⬜️") })
.onTapGesture{ print("you tapped on RoundedRectangle! 🟨") }
}
}
}
This looks like a bug indeed.
As a workaround you can use a custom shape, e.g. RoundedCorner taken from here:
struct RoundedCorner: Shape {
var radius: CGFloat = .infinity
var corners: UIRectCorner = .allCorners
func path(in rect: CGRect) -> Path {
let path = UIBezierPath(roundedRect: rect, byRoundingCorners: corners, cornerRadii: CGSize(width: radius, height: radius))
return Path(path.cgPath)
}
}
Then, it will work as expected:
struct ContentView: View {
var body: some View {
ZStack {
Color.red
.ignoresSafeArea()
.onTapGesture { print("you tapped on Screen Background! 🟥") }
Color.white
.frame(width: 300, height: 300, alignment: .center)
.onTapGesture { print("you tapped on RoundedRectangle Background! ⬜️") }
RoundedCorner(radius: 90)
.fill(Color.yellow)
.frame(width: 300, height: 300, alignment: .center)
.onTapGesture { print("you tapped on RoundedRectangle! 🟨") }
}
}
}
or, with Color.white as background:
struct ContentView: View {
var body: some View {
ZStack {
Color.red
.ignoresSafeArea()
.onTapGesture { print("you tapped on Screen Background! 🟥") }
RoundedCorner(radius: 90)
.fill(Color.yellow)
.frame(width: 300, height: 300, alignment: .center)
.onTapGesture { print("you tapped on RoundedRectangle! 🟨") }
.background(
Color.white
.onTapGesture { print("you tapped on RoundedRectangle Background! ⬜️") }
)
}
}
}
Here I got 2 shapes, one Rectangle and one Circle, which with action of a Button only one of them became visible to user, I tried to use #Namespace for this transform, but did not panned out!
MY Goal: Having a nice and smooth transform animation from one Shape to other.
struct ContentView: View {
#State var action: Bool = false
#Namespace var sameShape
var body: some View {
ZStack
{
Group
{
if action
{
Circle()
.fill(Color.blue).frame(width: 150, height: 150, alignment: .center)
.matchedGeometryEffect(id: "Dakota148Zero", in: sameShape)
}
else
{
Rectangle()
.fill(Color.red).frame(width: 150, height: 150, alignment: .center)
.matchedGeometryEffect(id: "Dakota148Zero", in: sameShape)
}
}
.animation(.easeInOut)
VStack
{
Spacer()
Button("transform") { action.toggle() }.font(Font.largeTitle).padding()
}
}
}
}
Here is way to do it by representing the circle and square as a RoundedRectangle with different cornerRadius values:
struct ContentView: View {
#State var action = false
var body: some View {
ZStack
{
RoundedRectangle(cornerRadius: action ? 0 : 75)
.fill(action ? Color.red : .blue)
.frame(width: 150, height: 150, alignment: .center)
.animation(.easeInOut)
VStack
{
Spacer()
Button("transform") {
action.toggle()
}
.font(Font.largeTitle)
.padding()
}
}
}
}
Group is not real container, so don't store animation. Replace Group with some stack, like
VStack
{
if action
// ... other code no change
With iOS14 out, you can use matchedGeometryEffect(). If you are using iOS14, I would recommend this approach.
https://www.hackingwithswift.com/quick-start/swiftui/how-to-synchronize-animations-from-one-view-to-another-with-matchedgeometryeffect
https://developer.apple.com/documentation/swiftui/view/matchedgeometryeffect(id:in:properties:anchor:issource:)
So in your solution, if you replace action.toggle() with withAnimation{self.action.toggle()} in your button code, it will animate.
Button("transform") {
withAnimation{self.action.toggle()}
}
.font(Font.largeTitle).padding()
This solution works on the simulator for me (Xcode 12.1, iPhone 11 iOS 14.1):
import SwiftUI
struct ContentView: View {
#State var action: Bool = false
#Namespace var transition
var body: some View {
ZStack {
Group {
if action {
Circle()
.fill(Color.blue).frame(width: 150, height: 150, alignment: .center)
.matchedGeometryEffect(id: "shape", in: transition)
} else {
Rectangle()
.fill(Color.red).frame(width: 150, height: 150, alignment: .center)
.matchedGeometryEffect(id: "shape", in: transition)
}
}
.animation(.easeInOut)
VStack {
Spacer()
Button("transform") { withAnimation{self.action.toggle()} }.font(Font.largeTitle).padding()
}
}
}
}
The matchedGeometryEffect() doesn't want to animate different shapes (including cornerRadius) or colors that nicely, not sure if this is a bug that will get fixed in future patches or just a feature that needs to be worked around by regular animations. With me playing around with matchedGeometryEffect(), it seems to do great with sizing things up and down, like shown with this code:
import SwiftUI
struct ContentView: View {
#State private var animate: Bool = false
#Namespace private var transition
var body: some View {
VStack {
if animate {
RoundedRectangle(cornerRadius: 75.0)
.matchedGeometryEffect(id: "shape", in: transition)
.frame(width: 250, height: 250, alignment: .center)
.foregroundColor(Color.blue)
.animation(.easeInOut)
.onTapGesture {
animate.toggle()
}
} else {
// Circle
RoundedRectangle(cornerRadius: 75.0)
.matchedGeometryEffect(id: "shape", in: transition)
.frame(width: 150, height: 150, alignment: .center)
.foregroundColor(Color.red)
.animation(.easeInOut)
.onTapGesture {
animate.toggle()
}
}
}
}
}