はじめに
DatePickerのカレンダーを表示できるボタンを作りたく、実装方法を調べてみました。
環境
Xcode 14.1
内容
struct DatePicker<Label> where Label : View
DatePicker
の使い方
DatePicker
を使うことでカレンダーから日付を選択できる
@State private var date = Date()
var body: some View {
DatePicker(
"Start Date",
selection: $date,
displayedComponents: [.date]
)
}
カレンダーから選択可能な期間を指定する場合は、ClosedRange<Date>
を使う
@State private var date = Date()
let dateRange: ClosedRange<Date> = {
let calendar = Calendar.current
let startComponents = DateComponents(year: 2021, month: 1, day: 1)
let endComponents = DateComponents(year: 2021, month: 12, day: 31, hour: 23, minute: 59, second: 59)
return calendar.date(from:startComponents)!
...
calendar.date(from:endComponents)!
}()
var body: some View {
DatePicker(
"Start Date",
selection: $date,
in: dateRange,
displayedComponents: [.date, .hourAndMinute]
)
}
datePickerStyle(_:)
を使うことで、表示方法を変えられる
@State private var date = Date()
var body: some View {
DatePicker(
"Start Date",
selection: $date,
displayedComponents: [.date, .hourAndMinute]
)
.datePickerStyle(.compact)
}
.compact |
.wheel |
.graphical |
---|---|---|
カレンダーの表示ができるButton①
実装
struct CustomCalendarButtonView: View {
@State var showDatePicker: Bool = false
@State var savedDate: Date? = nil
var body: some View {
ZStack {
HStack {
Button {
showDatePicker.toggle()
} label: {
Text("カレンダーを表示")
Image(systemName: "calendar")
}
.buttonStyle(.bordered)
}
if showDatePicker {
CustomDatePicker(
showDatePicker: $showDatePicker,
savedDate: $savedDate,
selectedDate: savedDate ?? Date()
)
.animation(.linear, value: savedDate)
.transition(.opacity)
}
}
}
}
struct CustomDatePicker: View {
@Binding var showDatePicker: Bool
@Binding var savedDate: Date?
@State var selectedDate: Date = Date()
var body: some View {
ZStack {
Color.black.opacity(0.3)
.edgesIgnoringSafeArea(.all)
.onTapGesture {
showDatePicker = false
}
VStack {
DatePicker(
"",
selection: $selectedDate,
displayedComponents: [.date, .hourAndMinute]
)
.datePickerStyle(.graphical)
Divider()
HStack {
Button("キャンセル") {
showDatePicker = false
}
Spacer()
Button("保存") {
savedDate = selectedDate
showDatePicker = false
}
}
.padding(.vertical, 15)
.padding(.horizontal, 10)
}
.padding(.horizontal, 20)
.background(
Color.white
.cornerRadius(30)
)
.padding(.horizontal, 20)
}
}
}
カレンダーの表示ができるButton②
実装
@State var showDatePicker = false
@State var date = Date()
var body: some View {
VStack {
Button {
showDatePicker.toggle()
} label: {
Text("カレンダーを表示")
Image(systemName: "calendar")
}
.buttonStyle(.bordered)
}
.frame(maxWidth: .infinity, maxHeight: .infinity)
.overlay {
ZStack{
if showDatePicker {
Color.black.opacity(0.3)
.edgesIgnoringSafeArea(.all)
.onTapGesture {
showDatePicker = false
}
DatePicker(
"",
selection: $date,
displayedComponents: [.date, .hourAndMinute]
)
.datePickerStyle(.graphical)
.padding()
.background(.white, in: RoundedRectangle(
cornerRadius: 10,
style: .continuous)
)
.padding()
}
}
.animation(.default, value: showDatePicker)
}
}
複数選択のできるカレンダーの表示
MultiDatePicker
を使うことで複数日が選択できるカレンダーが表示できる
struct MultiDatePicker<Label> where Label : View
実装
@State var showDatePicker = false
@State private var dates: Set<DateComponents> = []
var body: some View {
VStack {
Button {
showDatePicker.toggle()
} label: {
Text("カレンダーを表示")
Image(systemName: "calendar")
}
.buttonStyle(.bordered)
}
.frame(maxWidth: .infinity, maxHeight: .infinity)
.overlay {
ZStack{
if showDatePicker {
Color.black.opacity(0.3)
.edgesIgnoringSafeArea(.all)
.onTapGesture {
showDatePicker = false
}
MultiDatePicker(selection: $dates) {
Text("")
}
.datePickerStyle(.graphical)
.padding()
.background(.white, in: RoundedRectangle(
cornerRadius: 10,
style: .continuous)
)
.padding()
}
}
.animation(.default, value: showDatePicker)
}
}
おわりに
参考記事に助けられながら、実装したいものができました!
それと、MultiDatePicker
がiOS16から使えるようになったようですね
参考