I am fairly new in Swift(UI) and I am just trying to fiddle around and create myself a timeline like in the Calendar iOS app with the hours on the left and a divider per hour plus a red line where the current time is at.
I've seem to accomplish the first (hour and divider), but I am stuck on drawing the current time and position it correctly based on time and spacing.
Is anyone able to help me or guide me to the right direction? Thank you in advance!
My current code:
struct ContentView: View {
let dateFormatter = DateFormatter()
init(){
dateFormatter.dateFormat = "HH:mm"
}
var sortedTimeFrom: [Date] = {
let today = Calendar.current.date(bySettingHour: 0, minute: 0, second: 0, of: Date())!
var sortedTime: [Date] = []
var calender = Calendar(identifier: .iso8601)
calender.locale = Locale(identifier: "en_US_POSIX")
let currentHour = calender.component(.hour, from: today)
(0...(24)).forEach {
guard let newDate = calender.date(byAdding: .hour, value: $0, to: today),
calender.component(.hour, from: newDate) <= 23 else {
return
}
//convert date into desired format
sortedTime.append(newDate)
}
return sortedTime
}()
var body: some View {
ScrollView(.vertical)
{
ForEach(sortedTimeFrom, id: \.self) { date in
VStack(alignment: .leading){
HStack {
Spacer()
Text(date, formatter: dateFormatter)
VStack{
Color.gray.frame(height: 1 / UIScreen.main.scale)
}
}
}.frame(maxWidth: .infinity, alignment: .leading)
}
}
}
}
CodePudding user response:
You'll have to check every row for when the hour is equal to now, then calculate the offset based on the minutes & height of each row:
struct ContentView: View {
let dateFormatter = DateFormatter()
init(){
dateFormatter.dateFormat = "HH:mm"
}
var sortedTimeFrom: [Date] = {
let today = Calendar.current.date(bySettingHour: 0, minute: 0, second: 0, of: Date())!
var sortedTime: [Date] = []
var calender = Calendar(identifier: .iso8601)
calender.locale = Locale(identifier: "en_US_POSIX")
let currentHour = calender.component(.hour, from: today)
(0...(24)).forEach {
guard let newDate = calender.date(byAdding: .hour, value: $0, to: today),
calender.component(.hour, from: newDate) <= 23 else {
return
}
//convert date into desired format
sortedTime.append(newDate)
}
return sortedTime
}()
var currentDate: (Int, Double) {
let calendar = Calendar(identifier: .iso8601)
let hour = calendar.component(.hour, from: Date())
let minutes: Double = Double(calendar.component(.month, from: Date()))/60
return (hour, minutes)
}
var body: some View {
ScrollView(.vertical) {
VStack(spacing: 0) {
ForEach(sortedTimeFrom, id: \.self) { date in
VStack(alignment: .leading){
HStack {
Spacer()
Text(date, formatter: dateFormatter)
VStack{
Color.gray.frame(height: 1 / UIScreen.main.scale)
}
}
}.frame(maxWidth: .infinity, alignment: .leading)
.frame(height: 30)
.overlay(
VStack {
if Calendar(identifier: .iso8601).component(.hour, from: date) == currentDate.0 {
HStack {
Spacer()
Text(Date(), formatter: dateFormatter)
.foregroundColor(.red)
Color.red
.frame(height: 1 / UIScreen.main.scale)
}.offset(y: 30 * currentDate.1)
}
}
)
}
}
}
}
}