Reputation: 137
I am complete beginner with SwiftUI and I can't wrap my head around how to connect these images with views that represents lines. Now I simply have 3 VStacks with image and text and put them into a HStack, but don't know how to connect these images with a line shown in red in the picture I attached. Note that there's some space between the line and the image. I need general direction and some hints, full working code not necessary.
Thank you.
Upvotes: 0
Views: 443
Reputation: 1
I decided to give my answer which is same like aheze answer with this difference that you can have CustomVerticalAlignment as well! As I see in your Image in question you want that also:
with CustomVerticalAlignment: In center!
without CustomVerticalAlignment: off center!
import SwiftUI
struct ContentView: View {
var body: some View {
HStack(alignment: .customVerticalAlignment) {
VStack {
Image(systemName: "star")
.resizable()
.scaledToFit()
.frame(width: 50, height: 50, alignment: .center)
.padding()
.border(Color.black, width: 5)
.alignmentGuide(.customVerticalAlignment) { d in d[VerticalAlignment.center] }
Text("Text")
}
Capsule()
.fill(Color.red)
.frame(height: 5)
.alignmentGuide(.customVerticalAlignment) { d in d[VerticalAlignment.center] }
VStack {
Image(systemName: "star")
.resizable()
.scaledToFit()
.frame(width: 50, height: 50, alignment: .center)
.padding()
.border(Color.black, width: 5)
.alignmentGuide(.customVerticalAlignment) { d in d[VerticalAlignment.center] }
Text("Text")
}
Capsule()
.fill(Color.red)
.frame(height: 5)
.alignmentGuide(.customVerticalAlignment) { d in d[VerticalAlignment.center] }
VStack {
Image(systemName: "star")
.resizable()
.scaledToFit()
.frame(width: 50, height: 50, alignment: .center)
.padding()
.border(Color.black, width: 5)
.alignmentGuide(.customVerticalAlignment) { d in d[VerticalAlignment.center] }
Text("Text")
}
}
.padding()
}
}
extension VerticalAlignment {
struct CustomVerticalAlignment: AlignmentID {
static func defaultValue(in d: ViewDimensions) -> CGFloat {
d[VerticalAlignment.center]
}
}
static let customVerticalAlignment = VerticalAlignment(CustomVerticalAlignment.self)
}
About this version: I would say it does the same job of version 1.0.0 in less code and also Text and Line are not depending on VStack or eachother any moere!
import SwiftUI
struct ContentView: View {
var body: some View {
HStack {
image.overlay(text.offset(y: 40), alignment: .bottom)
capsule
image.overlay(text.offset(y: 40), alignment: .bottom)
capsule
image.overlay(text.offset(y: 40), alignment: .bottom)
}
.padding(50)
}
var image: some View {
return Image(systemName: "star.fill")
.resizable()
.scaledToFit()
.padding(10)
.shadow(radius: 10)
.frame(width: 50, height: 50, alignment: .center)
.foregroundColor(Color.red)
.background(Color.yellow)
.border(Color.black, width: 5)
}
var capsule: some View {
return Capsule()
.fill(Color.red)
.frame(height: 5)
}
var text: some View {
return Text("Hello World!")
.lineLimit(1)
.fixedSize()
}
}
Upvotes: 2
Reputation: 30336
How's this?
In SwiftUI, you use HStack
s and VStack
s to stack your Views. For the red line, a Rectangle
should do. Here's the code:
struct ContentView: View {
var body: some View {
HStack { /// horizontal stack
VStack {
Image(systemName: "face.smiling")
.font(.system(size: 80))
.padding()
.border(Color.black, width: 5)
Text("Text TEXTEXT")
}
Rectangle()
.fill(Color.red)
.frame(height: 5)
VStack {
Image(systemName: "face.smiling")
.font(.system(size: 80))
.padding()
.border(Color.black, width: 5)
Text("Text TEXTEXT")
}
Rectangle()
.fill(Color.red)
.frame(height: 5)
VStack {
Image(systemName: "face.smiling")
.font(.system(size: 80))
.padding()
.border(Color.black, width: 5)
Text("Text TEXTEXT")
}
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
.previewLayout(.fixed(width: 800, height: 200))
}
}
Upvotes: 2
Reputation: 52407
You could define a Shape
that represents your line.
I used the spacing
parameter of HStack
to do the spacing:
struct MyLine : Shape {
func path(in rect: CGRect) -> Path {
Path { path in
path.move(to: CGPoint(x: 0, y: rect.midY))
path.addLine(to: CGPoint(x: rect.maxX, y: rect.midY))
}
}
}
struct ContentView: View {
var body: some View {
HStack(spacing: 10) {
VStack {
Image(systemName: "pencil")
Text("Label")
}
MyLine().stroke(Color.red)
VStack {
Image(systemName: "pencil")
Text("Label 2")
}
MyLine().stroke(Color.red)
VStack {
Image(systemName: "pencil")
Text("Label 3")
}
}
}
}
You could add a lineWidth
parameter to make the stroke
thicker:
.stroke(Color.red, lineWidth: 4)
Also, if you didn't using spacing
on the HStack
, you could using a padding
modifier on either the VStack
s or the MyLine
s to get the spacing.
Upvotes: 1