在SwiftUI中将下一个/上一个按钮添加到FSCalendar
我一直在玩,它帮助我建立了自己的定制日历 因为它是用UIKit编写的,所以我在将它集成到我的SwiftUI项目中时遇到了一些问题,例如在日历的两侧添加“下一个”和“上一个”按钮 这就是我到目前为止所做的: ContentView,我用一个HStack将按钮添加到日历的侧面在SwiftUI中将下一个/上一个按钮添加到FSCalendar,swiftui,fscalendar,Swiftui,Fscalendar,我一直在玩,它帮助我建立了自己的定制日历 因为它是用UIKit编写的,所以我在将它集成到我的SwiftUI项目中时遇到了一些问题,例如在日历的两侧添加“下一个”和“上一个”按钮 这就是我到目前为止所做的: ContentView,我用一个HStack将按钮添加到日历的侧面 struct ContentView: View { let myCalendar = MyCalendar() var body: some View { HStack(spacing: 5) { B
struct ContentView: View {
let myCalendar = MyCalendar()
var body: some View {
HStack(spacing: 5) {
Button(action: {
myCalendar.previousTapped()
}) { Image("back-arrow") }
MyCalendar()
Button(action: {
myCalendar.nextTapped()
}) { Image("next-arrow") }
}
}}
以及MyCalendar结构,为了集成FSCalendar库,它是一个UIViewRepresentable。
这也是我添加了两个功能(nextTapped和previousTapped)的地方,这两个功能应该会在点击按钮时更改显示的月份:
struct MyCalendar: UIViewRepresentable {
let calendar = FSCalendar(frame: CGRect(x: 0, y: 0, width: 320, height: 300))
func makeCoordinator() -> Coordinator {
Coordinator(self)
}
func makeUIView(context: Context) -> FSCalendar {
calendar.delegate = context.coordinator
calendar.dataSource = context.coordinator
return calendar
}
func updateUIView(_ uiView: FSCalendar, context: Context) {
}
func nextTapped() {
let nextMonth = Calendar.current.date(byAdding: .month, value: 1, to: calendar.currentPage)
calendar.setCurrentPage(nextMonth!, animated: true)
print(calendar.currentPage)
}
func previousTapped() {
let previousMonth = Calendar.current.date(byAdding: .month, value: -1, to: calendar.currentPage)
calendar.setCurrentPage(previousMonth!, animated: true)
print(calendar.currentPage)
}
class Coordinator: NSObject, FSCalendarDelegateAppearance, FSCalendarDataSource, FSCalendarDelegate {
var parent: MyCalendar
init(_ calendar: MyCalendar) {
self.parent = calendar
}
func minimumDate(for calendar: FSCalendar) -> Date {
return Date()
}
func maximumDate(for calendar: FSCalendar) -> Date {
return Date().addingTimeInterval((60 * 60 * 24) * 365)
}
}}
这就是它在模拟器中的样子:
正如您所看到的,只要点击下一个或上一个按钮,我就可以在终端上打印当前页面,但是当前页面在实际日历中没有改变。
如何解决此问题?因为您正在使用
UIViewRepresentable
协议将UIView类与SwiftUI绑定在一起。在这里,您必须将-类型的对象与发布者一起使用,该发布者在对象更改之前发出消息。
您可以检查下面的代码以获得结果输出:(最欢迎编辑/改进)
输出:
接近它时,不要考虑在UIKit中如何完成(即忘记目标操作)。在ContentView中设置状态,如
currentDate
。这些按钮将改变这种状态。然后让日历在日期更改时做出响应-将date属性作为绑定传递到MyCalendar,协调器(不应该有对结构的引用,而是对UIView的引用)将在日期更改时通过更新MyCalendar结构的UIView进行响应。谢谢!这正是我需要的!
import SwiftUI
import UIKit
import FSCalendar
class CalendarData: ObservableObject{
@Published var selectedDate : Date = Date()
@Published var titleOfMonth : Date = Date()
@Published var crntPage: Date = Date()
}
struct ContentView: View {
@ObservedObject private var calendarData = CalendarData()
var strDateSelected: String {
let dateFormatter = DateFormatter()
dateFormatter.dateStyle = .medium
dateFormatter.timeStyle = .none
dateFormatter.locale = Locale.current
return dateFormatter.string(from: calendarData.selectedDate)
}
var strMonthTitle: String {
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "MMMM yyyy"
dateFormatter.locale = Locale.current
return dateFormatter.string(from: calendarData.titleOfMonth)
}
var body: some View {
VStack {
HStack(spacing: 100) {
Button(action: {
self.calendarData.crntPage = Calendar.current.date(byAdding: .month, value: -1, to: self.calendarData.crntPage)!
}) { Image(systemName: "arrow.left") }
.frame(width: 35, height: 35, alignment: .leading)
Text(strMonthTitle)
.font(.headline)
Button(action: {
self.calendarData.crntPage = Calendar.current.date(byAdding: .month, value: 1, to: self.calendarData.crntPage)!
}) { Image(systemName: "arrow.right") }
.frame(width: 35, height: 35, alignment: .trailing)
}
CustomCalendar(dateSelected: $calendarData.selectedDate, mnthNm: $calendarData.titleOfMonth, pageCurrent: $calendarData.crntPage)
.padding()
.background(
RoundedRectangle(cornerRadius: 25.0)
.foregroundColor(.white)
.shadow(color: Color.black.opacity(0.2), radius: 10.0, x: 0.0, y: 0.0)
)
.frame(height: 350)
.padding(25)
Text(strDateSelected)
.font(.title)
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
struct CustomCalendar: UIViewRepresentable {
typealias UIViewType = FSCalendar
@Binding var dateSelected: Date
@Binding var mnthNm: Date
@Binding var pageCurrent: Date
var calendar = FSCalendar()
var today: Date{
return Date()
}
func makeUIView(context: Context) -> FSCalendar {
calendar.dataSource = context.coordinator
calendar.delegate = context.coordinator
calendar.appearance.headerMinimumDissolvedAlpha = 0
return calendar
}
func updateUIView(_ uiView: FSCalendar, context: Context) {
uiView.setCurrentPage(pageCurrent, animated: true) // --->> update calendar view when click on left or right button
}
func makeCoordinator() -> CustomCalendar.Coordinator {
Coordinator(self)
}
class Coordinator: NSObject, FSCalendarDelegate, FSCalendarDataSource {
var parent: CustomCalendar
init(_ parent: CustomCalendar) {
self.parent = parent
}
func calendar(_ calendar: FSCalendar, didSelect date: Date, at monthPosition: FSCalendarMonthPosition) {
parent.dateSelected = date
}
func calendarCurrentPageDidChange(_ calendar: FSCalendar) {
parent.pageCurrent = calendar.currentPage
parent.mnthNm = calendar.currentPage
}
}
}