My recommendation would be to have each portion of the ruler be a `Shape` with an associated `enum` to represent the tick marks needed. Each iteration of the shape would draw exactly 1 section of the ruler. By doing this, you gain more control and more precision as to how to draw it, with 1 `ForEach` and simple repeatability. The shape could be defined as:
struct Unit: Shape {
let num: Int
let ticks: [Tick]
func path(in rect: CGRect) -> Path {
let distance = rect.width / CGFloat(ticks.count)
var path = Path()
var x = rect.minX
for tick in ticks {
switch tick {
case .major:
path.move(to: CGPoint(x: x, y: rect.minY))
path.addLine(to: CGPoint(x: x, y: rect.maxY))
case .mid:
path.move(to: CGPoint(x: x, y: rect.maxY))
path.addLine(to: CGPoint(x: x, y: rect.maxY - 16))
case .minor:
path.move(to: CGPoint(x: x, y: rect.maxY))
path.addLine(to: CGPoint(x: x, y: rect.maxY - 8))
}
x += distance
print("tick")
}
return path
}
}
enum Tick {
case major, mid, minor
}
Then your view would simplify to this:
struct Ruler: View {
let ticks: [Tick] = [.major, .minor, .mid, .minor, .mid, .minor, .mid, .minor]
var body: some View {
ScrollView(.horizontal, showsIndicators: false) {
HStack(spacing: 0) {
ForEach(1...20, id: \.self) { num in
Unit(num: num, ticks: ticks)
.stroke(.white, lineWidth: 2)
.frame(width: 100)
.overlay(
Text("\(num)")
.padding(.trailing, 2)
.foregroundColor(.white),
alignment: .topTrailing
)
}
}
.frame(height: 40)
.padding(.top, 2)
.padding(.bottom, 1)
.background(Color.black)
}
.padding()
}
}
[![enter image description here][1]][1]
**Login Page design using `SwiftUI`**
import SwiftUI
struct ContentView: View {
@State var email: String = "william@gmail.com"
@State var password: String = ""
@State static var labelTitle: String = ""
var body: some View {
VStack(alignment: .center){
//Label
Text("Login").font(.largeTitle).foregroundColor(.yellow).bold()
//TextField
TextField("Email", text: $email)
.textContentType(.emailAddress)
.foregroundColor(.blue)
.frame(minHeight: 40)
.background(RoundedRectangle(cornerRadius: 10).foregroundColor(Color.green))
TextField("Password", text: $password) //Placeholder
.textContentType(.newPassword)
.frame(minHeight: 40)
.foregroundColor(.blue) // Text color
.background(RoundedRectangle(cornerRadius: 10).foregroundColor(Color.green))
//Button
Button(action: {
}) {
HStack {
Image(uiImage: UIImage(named: "Login")!)
.renderingMode(.original)
.font(.title)
.foregroundColor(.blue)
Text("Login")
.font(.title)
.foregroundColor(.white)
}
.font(.headline)
.frame(minWidth: 0, maxWidth: .infinity)
.background(LinearGradient(gradient: Gradient(colors: [Color("DarkGreen"), Color("LightGreen")]), startPoint: .leading, endPoint: .trailing))
.cornerRadius(40)
.padding(.horizontal, 20)
.frame(width: 200, height: 50, alignment: .center)
}
Spacer()
}.padding(10)
.frame(minWidth: 0, idealWidth: .infinity, maxWidth: .infinity, minHeight: 0, idealHeight: .infinity, maxHeight: .infinity, alignment: .top)
.background(Color.gray)
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
[1]: https://i.stack.imgur.com/M0P2h.png