Reputation: 13
I'm almost sure that there is a simple solution, but after several years of using UIKit, it's not very obvious for me.
There are in fact a calendar with seven buttons to switch days of the week. I use a constant padding value between buttons, but I need to divide view's frame to seven equal parts, one for each button to adapt the layout for different screen sizes. It's a very easy task in frame layout, but I can't guess how to do this right with SwiftUI. Spacer()
in this case look not very nice.
Some pictures to clear what's going on: what I want, what I have.
Thanks!
struct WeekCalendarView: View {
@ObservedObject var selectedDay: ObservableDate
private var days: [Date] {
return selectedDay.date.currentWeek
}
var body: some View {
HStack {
ForEach(days, id: \.self) { day in
Button(action: {
self.selectedDay.date = day
}) {
VStack {
Text(day.date)
.fontWeight(.semibold)
.foregroundColor(day == self.selectedDay.date ? Color.white : Color.black)
.padding(14)
.background(day == self.selectedDay.date ? Color.green : Color.clear)
.clipShape(Circle())
.padding(.vertical, 6)
Text(day.dayOfTheWeek)
.fontWeight(.light)
.font(.caption)
}
}
.buttonStyle(PlainButtonStyle())
}
}
}
}
Upvotes: 1
Views: 1161
Reputation: 8091
Roland did not test his solution, so there were some mistakes in it, here is a tested solution based on Rolands answer:
changes: spacing has to be set to 0 in HStack, else the result is still ugly. And there was a small type "with" ...
struct ContentView: View {
var days = [
Day(date: "9", dayOfTheWeek: "Su"),
Day(date: "10", dayOfTheWeek: "Mo"),
Day(date: "11", dayOfTheWeek: "Tu"),
Day(date: "12", dayOfTheWeek: "We"),
Day(date: "13", dayOfTheWeek: "Th"),
Day(date: "14", dayOfTheWeek: "Fr"),
Day(date: "15", dayOfTheWeek: "Sa")
]
@State var selectedDay : Day = Day(date: "10", dayOfTheWeek: "Mo")
var body: some View {
HStack(spacing:0) {
ForEach(days, id: \.self) { day in
Button(action: {
self.selectedDay = day
}) {
VStack {
Text(day.date)
.fontWeight(.semibold)
.foregroundColor(day == self.selectedDay ? Color.white : Color.black)
.padding(14)
.background(day == self.selectedDay ? Color.green : Color.clear)
.clipShape(Circle())
.padding(.vertical, 6)
Text(day.dayOfTheWeek)
.fontWeight(.light)
.font(.caption)
}
.frame(width: screen.size.width / 7) // This is where I would use the screen size.
}
.buttonStyle(PlainButtonStyle())
}
}
}
}
Upvotes: 0
Reputation: 257719
Here is a demo of automatic platform-independent layout (w/o padding) on replicated model.
Demo prepared & tested with Xcode 12 / iOS 14
struct WeekCalendarView: View {
private var days = [23, 24, 25, 26, 27, 28, 29]
private var dayOfTheWeek = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sut"]
@State private var selectedDay = 24
var body: some View {
HStack {
ForEach(0..<days.count, id: \.self) { day in
Button(action: {
self.selectedDay = days[day]
}) {
VStack {
Circle()
.fill(days[day] == self.selectedDay ? Color.green : Color.clear)
.aspectRatio(contentMode: .fit)
.overlay(
Text("\(days[day])")
.fontWeight(.semibold).fixedSize()
.foregroundColor(days[day] == self.selectedDay ? Color.white : Color.black)
)
.padding(.vertical, 6)
.frame(maxWidth: .infinity)
Text(dayOfTheWeek[day])
.fontWeight(.light)
.font(.caption)
}
}
.buttonStyle(PlainButtonStyle())
}
}
}
}
Upvotes: 1