如何解决ScrollView SwiftUI
我用SwiftUI构建了一个简单的水平日历,它工作正常。但我希望它在应用启动时自动滚动到当前日期。我怎样才能做到这一点?我假设我应该使用GeometryReader来获取具有当前日期的帧的位置并基于该日期设置偏移量,但是ScrollView没有内容偏移量修饰符。我知道在iOS 14中现在有了ScrollViewReader,但是iOS 13呢?
struct MainCalendar: View {
@Environment(\.calendar) var calendar
@State private var month = Date()
@State private var selectedDate: Date = Date()
var body: some View {
vstack(spacing: 30) {
MonthAndYearView(date: $month)
WeekDaysView(date: month)
}
.padding(.vertical)
}
}
struct MonthAndYearView: View {
@Environment(\.calendar) var calendar
private let formatter = DateFormatter.monthAndYear
@Binding var date: Date
var body: some View {
HStack(spacing: 20) {
Button(action: {
self.date = calendar.date(byAdding: .month,value: -1,to: date)!
},label: {
Image(systemName: "chevron.left")
})
Text(formatter.string(from: date))
.font(.system(size: 18,weight: .semibold))
Button(action: {
self.date = calendar.date(byAdding: .month,value: 1,label: {
Image(systemName: "chevron.right")
})
}
}
}
struct WeekDaysView: View {
@Environment(\.calendar) var calenar
let date: Date
var body: some View {
ScrollView(.horizontal,showsIndicators: false) {
HStack(spacing: 30) {
ForEach(days,id: \.self) { day in
vstack(spacing: 20) {
Text(daySymbol(date: day))
.font(.system(size: 14,weight: .regular))
if calenar.isDateInToday(day) {
Text("\(dayNumber(date: day))")
.foregroundColor(Color.white)
.background(Circle().foregroundColor(.blue)
.frame(width: 40,height: 40))
} else {
Text("\(dayNumber(date: day))")
}
}
}
}
.padding([.horizontal])
.padding(.bottom,15)
}
}
private func dayNumber(date: Date) -> String {
let formatter = DateFormatter.dayNumber
let dayNumber = formatter.string(from: date)
return dayNumber
}
private var days: [Date] {
guard let interval = calenar.dateInterval(of: .month,for: date) else { return [] }
return calenar.generateDates(inside: interval,matching: DateComponents(hour: 0,minute: 0,second: 0))
}
private func daySymbol(date: Date) -> String {
let dayFormatter = DateFormatter.weekDay
let weekDay = dayFormatter.string(from: date)
return weekDay
}
}
解决方法
这个库https://github.com/Amzd/ScrollViewProxy解决了我的问题。
struct WeekDaysView: View {
let date: Date
@Environment(\.calendar) var calendar
@State private var scrollTarget: Int? = nil
var body: some View {
ScrollViewReader { proxy in
ScrollView(.horizontal,showsIndicators: false) {
HStack(spacing: 30) {
ForEach(Array(zip(days.indices,days)),id: \.0) { index,day in
VStack(spacing: 20) {
Text(daySymbol(date: day))
.font(.system(size: 14,weight: .regular))
.scrollId(index)
if calendar.isDateInToday(day) {
Text("\(dayNumber(date: day))")
.foregroundColor(Color.white)
.background(Circle().foregroundColor(.blue)
.frame(width: 40,height: 40))
.onAppear {
scrollTarget = index
}
} else {
Text("\(dayNumber(date: day))")
}
}
}
}
.padding([.horizontal])
.padding(.bottom,15)
}
.onAppear {
DispatchQueue.main.async {
withAnimation {
proxy.scrollTo(scrollTarget,alignment: .center,animated: true)
}
}
}
}
}
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。