Goal:
Match SwiftUI position coordinates with Figma.
Context:
On Figma, the anchor is at the top leading of the layer.
On SwiftUI, the anchor is at the center of the layer, as the documentation mentions:
/// - Returns: A view that fixes the center of this view at `x` and `y`.
#inlinable public func position(x: CGFloat = 0, y: CGFloat = 0) -> some View
So when both SwiftUI and Figma are set to x:0 and y:0 positions, they don't match.
Question: how can I set the anchor in SwiftUI to be at the top leading corner?
import SwiftUI
struct ContentView: View {
var body: some View {
ZStack {
Circle()
.frame(width: 132.0, height: 132.0)
.position(x: 0, y: 0)
}
.frame(width: 731, height: 418)
.background(.blue)
}
}
Centering the circle at (0, 0) will make go out of bounds because of the radius. You must do one of the following:
Using HStack & VStack:
ZStack {
VStack {
HStack {
Circle()
.frame(width: 132.0, height: 132.0)
Spacer()
}
Spacer()
}
}.frame(width: 731, height: 418)
.background(.blue)
Center the circle at (x + radius, y + radius):
ZStack {
HStack {
Circle()
.frame(width: 132.0, height: 132.0)
}
.position(x: 66, y: 66)
}
.frame(width: 731, height: 418)
.background(.blue)
Related
I am trying to make a 3D carousel horizontal scroll view but when you scroll, it disappears and glitches. This is very strange for a ScrollView as I have used a horizontal scroll view many times before and have not encountered such an issue. What should I consider when constructing my horizontal scroll view? Is there something in my code that is faulty? Please look at my code below:
struct TestView: View {
var body: some View {
ZStack {
Color.black.ignoresSafeArea()
ScrollView(.horizontal, showsIndicators: false) {
HStack(alignment: .center, spacing: 230) {
ForEach(0..<5, id: \.self) { item in
GeometryReader { geometry in
Rectangle()
.fill(.ultraThinMaterial)
.frame(width: 200, height: 300, alignment: .center)
.cornerRadius(16)
.shadow(color: Color.black.opacity(0.2), radius: 20, x: 0, y: 0)
.rotation3DEffect(Angle(degrees: (Double(geometry.frame(in: .global).minX) - 210) / -20), axis: (x: 0, y: 1.0, z: 0))
}
}
}
.padding(.horizontal, 210)
}
}
}
}
I was doing some practice in swift ui I made a tab bar like in the picture and I want to move it to the bottom of the screen, but I could not spacer did not work, maybe it is related to the path also I want to give corner radius I am new yet switui thank you in advance for your answers
struct ContentView: View {
var body: some View {
VStack {
Spacer()
CustomTabBar()
}
}}
struct CustomTabBar: View {
var body: some View {
ZStack {
Path { path in
path.addRect(CGRect(x: 10, y: 200, width: UIScreen.main.bounds.size.width - 20, height: 80))
}
.cornerRadius(40)
.foregroundColor(.blue)
Path { path in
path.addArc(center: CGPoint(x: UIScreen.main.bounds.size.width / 2, y: 200), radius: 50, startAngle: .degrees(0), endAngle: .degrees(180), clockwise: false)
}.foregroundColor(.white)
}
}}
Yes, you are right. It's related to the Path elements you have. I would do the same with pure SwiftUI Shapes, Rectangle and Circle. This also eases your work with corner radius.
Here's my code:
struct ContentView: View {
var body: some View {
VStack {
Spacer()
CustomTabBar()
}
}
}
struct CustomTabBar: View {
var body: some View {
ZStack {
Rectangle()
.frame(height: 80)
.foregroundColor(Color.blue)
.cornerRadius(40)
.padding(.horizontal, 10)
Circle()
.frame(width: 100, height: 100)
.foregroundColor(Color.white)
.offset(x: 0, y: -50)
}
}
}
This produces the following result:
I have a simple horizontal stack comprising three colour bars:
When the yellow bar width is magnified via a gesture, I would expect the purple bar to move to the right to accommodate the expanded yellow bar but instead the yellow bar simply expands UNDERNEATH the purple bar (which remains in into original position).
struct ContentView: View {
#GestureState var scale = CGFloat(1)
var body: some View {
HStack(spacing: 5) {
Color(.blue)
.frame(width: 100, height: 60, alignment: .leading)
Color(.yellow)
.frame(width: 100, height: 60, alignment: .leading)
.scaleEffect(x: scale, y: 1.0, anchor: .leading)
.gesture(MagnificationGesture()
.updating($scale, body: { (value, scale, trans) in
scale = value
})
)
Color(.purple)
.frame(width: 100, height: 60, alignment: .leading)
}
}
}
How can I achieve dynamic adjustment of the HStack layout whilst one of its components is expanding?
Many thanks...
Robert
you could try this code:
Color(.yellow)
.frame(width: CGFloat(100) * scale, height: 60, alignment: .leading)
.gesture(MagnificationGesture()
.updating($scale, body: { (value, scale, trans) in
scale = value
})
)
I'm trying to achieve something that is quite easy in UIKit - one view that is always in in the center (image) and the second view (text) is on top of it with some spacing between two views. I tried many different approaches (mainly using alignmentGuide but nothing worked as I'd like).
code:
ZStack {
Rectangle()
.foregroundColor(Color.red)
VStack {
Text("Test")
.padding([.bottom], 20) // I want to define spacing between two views
Image(systemName: "circle")
.resizable()
.alignmentGuide(VerticalAlignment.center, computeValue: { value in
value[VerticalAlignment.center] + value.height
})
.frame(width: 20, height: 20)
}
}
.frame(width: 100, height: 100)
result:
As you can see image is not perfectly centered and it actually depends on the padding value of the Text. Is there any way to force vertical and horizontal alignment to be centered in the superview and layout second view without affecting centered view?
I think the “correct” way to do this is to define a custom alignment:
extension VerticalAlignment {
static var custom: VerticalAlignment {
struct CustomAlignment: AlignmentID {
static func defaultValue(in context: ViewDimensions) -> CGFloat {
context[VerticalAlignment.center]
}
}
return .init(CustomAlignment.self)
}
}
Then, tell your ZStack to use the custom alignment, and use alignmentGuide to explicitly set the custom alignment on your circle:
PlaygroundPage.current.setLiveView(
ZStack(alignment: .init(horizontal: .center, vertical: .custom)) {
Color.white
Rectangle()
.fill(Color.red)
.frame(width: 100, height: 100)
VStack {
Text("Test")
Circle()
.stroke(Color.white)
.frame(width: 20, height: 20)
.alignmentGuide(.custom, computeValue: { $0.height / 2 })
}
}
.frame(width: 300, height: 300)
)
Result:
You can center the Image by moving it to ZStack. Then apply .alignmentGuide to the Text:
struct ContentView: View {
var body: some View {
ZStack {
Rectangle()
.foregroundColor(Color.red)
Text("Test")
.alignmentGuide(VerticalAlignment.center) { $0[.bottom] + $0.height }
Image(systemName: "circle")
.resizable()
.frame(width: 20, height: 20)
}
.frame(width: 100, height: 100)
}
}
Note that as you specify the width/height of the Image explicitly:
Image(systemName: "circle")
.resizable()
.frame(width: 20, height: 20)
you can specify the .alignmentGuide explicitly as well:
.alignmentGuide(VerticalAlignment.center) { $0[.bottom] + 50 }
Here is possible alternate, using automatic space consuming feature
Tested with Xcode 12 / iOS 14
struct ContentView: View {
var body: some View {
ZStack {
Rectangle()
.foregroundColor(Color.red)
VStack(spacing: 0) {
Color.clear
.overlay(
Text("Test").padding([.bottom], 10),
alignment: .bottom)
Image(systemName: "circle")
.resizable()
.frame(width: 20, height: 20)
Color.clear
}
}
.frame(width: 100, height: 100)
}
}
Note: before I used Spacer() for such purpose but with Swift 2.0 it appears spacer becomes always just a spacer, ie. nothing can be attached to it - maybe bug.
I want to position blue view based on topTrailing anchor like this
not like
this is my code Xcode12 beta 3
struct Test: View {
var body: some View {
ZStack(alignment:.topLeading){
Color.black
Rectangle()
.frame(width:100, height: 100, alignment: .topLeading)
.position(CGPoint(x: 0, y: 0))
.foregroundColor(.blue)
}
.frame(width: 250, height: 250, alignment: .topLeading)
}
}
how do I do that
To position relative to the top leading origin:
Use
.offset(x: 0, y: 0)
in place of
.position(CGPoint(x: 0, y: 0))
Just remove position, it disables automatic layout, because specifies explicit defined location in parent coordinates relative to own anchor point.
struct Test: View {
var body: some View {
ZStack(alignment:.topLeading){
Color.black
Rectangle()
.frame(width:100, height: 100, alignment: .topLeading)
.foregroundColor(.blue)
}
.frame(width: 250, height: 250, alignment: .topLeading)
}
}