我不知道在视图占位符中放什么
I don't know what to put in the view placeholder
即使“proxy”是状态变量,我仍然在插入“proxy: /GeometryProxy/”时出错。我有下面的预览代码。我不知道在占位符中放什么,我很困惑。我已经包含了我的完整代码以供审查。请往下看
struct MathematicallyMainController_Previews: PreviewProvider {
static var previews: some View {
MathematicallyMainController(proxy: // what do i put here?)
}
}
我的完整代码:
这就是 'var' 的问题所在。
struct MathematicallyMainController: View {
@StateObject var tabBarModel = TabBarViewModel()
@Environment(\.colorScheme) var colorScheme
@State var selectedIndex = 0
@State var isSelectedA = false
@State var isSelectedB = false
@State var isSelectedC = false
@State var isSelectedD = false
@State var isSelectedE = false
@State var proxy: GeometryProxy
var body: some View {
ZStack {
let bottomEdge = proxy.safeAreaInsets.bottom
switch selectedIndex {
case 0:
HomeViewController()
case 1:
BrowseView()
case 2:
RewardsView()
case 3:
EssentialsView()
case 4:
SchoolModeView()
default:
HomeViewController()
}
ZStack {
RoundedRectangle(cornerRadius: 15)
.fill(.regularMaterial)
.colorScheme(colorScheme == .dark ? .dark : .light)
HStack(alignment: .center) {
Button {
selectedIndex = 0
} label: {
if selectedIndex == 0 {
ZStack {
Circle()
.blur(radius: 20)
.foregroundColor(.blue)
.frame(width: 60)
.padding([.leading, .trailing], 5)
Image(systemName: "house.fill")
.font(.title)
.foregroundColor(colorScheme == .dark ? .black : .white)
.padding([.leading, .trailing], 5)
}
} else {
Image(systemName: "house.fill")
.font(.title)
.foregroundColor(colorScheme == .dark ? .white : .black)
}
}
Button {
selectedIndex = 1
} label: {
if selectedIndex == 1 {
ZStack {
Circle()
.blur(radius: 20)
.foregroundColor(.indigo)
.frame(width: 60)
.padding(.leading, 15)
Image(systemName: "rectangle.stack.fill")
.font(.title)
.foregroundColor(colorScheme == .dark ? .black : .white)
.padding(.leading, 15)
}
} else {
Image(systemName: "rectangle.stack.fill")
.font(.title)
.foregroundColor(colorScheme == .dark ? .white : .black)
.padding(.leading, 15)
}
}
Button {
selectedIndex = 2
} label: {
if selectedIndex == 2 {
ZStack {
Circle()
.blur(radius: 20)
.foregroundColor(.orange)
.frame(width: 60)
.padding([.trailing, .leading], 15)
Image(systemName: "circle.dotted")
.font(.title)
.foregroundColor(colorScheme == .dark ? .black : .white)
.padding([.trailing, .leading], 15)
}
} else {
Image(systemName: "circle.dotted")
.font(.title)
.foregroundColor(colorScheme == .dark ? .white : .black)
.padding(.trailing, 15)
.padding(.leading, 15)
}
}
Button {
selectedIndex = 3
} label: {
if selectedIndex == 3 {
ZStack {
Circle()
.blur(radius: 20)
.foregroundColor(.green)
.frame(width: 60)
.padding(.trailing, 15)
Image(systemName: "doc.text.image")
.font(.title)
.foregroundColor(colorScheme == .dark ? .black : .white)
.padding(.trailing, 15)
}
} else {
Image(systemName: "doc.text.image")
.font(.title)
.foregroundColor(colorScheme == .dark ? .white : .black)
.padding(.trailing, 15)
}
}
Button {
selectedIndex = 4
} label: {
if selectedIndex == 4 {
ZStack {
Circle()
.blur(radius: 20)
.foregroundColor(.purple)
.frame(width: 60)
.padding([.leading, .trailing], 5)
Image(systemName: "graduationcap.fill")
.font(.title)
.foregroundColor(colorScheme == .dark ? .black : .white)
.padding([.leading, .trailing], 5)
}
} else {
Image(systemName: "graduationcap.fill")
.font(.title)
.foregroundColor(colorScheme == .dark ? .white : .black)
}
}
}
.colorScheme(colorScheme == .dark ? .dark : .light)
.padding(.horizontal)
}
.frame(height: 60)
.shadow(color: .primary, radius: -10)
.shadow(color: .black, radius: 10)
.padding([.horizontal])
.padding(.bottom)
.frame(maxHeight: .infinity, alignment: .bottom)
.modifier(OffsetModifier())
.environmentObject(tabBarModel)
.offset(y: tabBarModel.tabState == .floating ? 0 : bottomEdge)
}
}
}
这是我用来创建滚动动画的 ViewModifier。
struct OffsetModifier: ViewModifier {
@EnvironmentObject var model: TabBarViewModel
func body(content: Content) -> some View {
content
.overlay(
GeometryReader { proxy -> Color in
let minY = proxy.frame(in: .global).minY
DispatchQueue.main.async {
let durationOffset: CGFloat = 35
if minY < model.offset {
if model.offset < 0 && -minY > (model.lastStoredOffset + durationOffset) {
withAnimation(.easeOut.speed(1)) {
model.tabState = .floating
}
model.lastStoredOffset = -model.offset
}
}
if minY > model.offset && -minY < (model.lastStoredOffset + durationOffset) {
withAnimation(.easeOut.speed(1)) {
model.tabState = .expanded
}
model.lastStoredOffset = -model.offset
}
model.offset = minY
}
return Color.clear
}
,alignment: .top
)
}
}
你唯一一次使用 proxy
是在这一行:
let bottomEdge = proxy.safeAreaInsets.bottom
因此,没有理由传递整个 GeometryProxy
-- 您可以传递底部插图。此外,它绝对不需要是 @State
变量——当 View
需要随时间改变其状态时使用 @State
—— 这只是传入的参数.
更改此行:
@State var proxy: GeometryProxy
至:
var bottomInset : CGFloat = 0
因为它有一个默认值,所以你的预览可以变成这样:
static var previews: some View {
MathematicallyMainController()
}
如果你真的想传递一个值(比如,从 View
的父级),你可以这样做:
GeometryReader { proxy in
//other view code...
MathematicallyMainController(bottomInset: proxy.safeAreaInsets.bottom)
//other code...
}
也可以选择将 GeometryReader
移到 MathematicallyMainController
内,但我假设您一开始将它移到外面是有原因的。
综上所述,您似乎有一些可以清理的不必要和未使用的代码。例如,isSelectedA-E
变量中的 none 曾经被使用过。这里可能还有更多可以重构的东西,但不在当前问题的范围内。
即使“proxy”是状态变量,我仍然在插入“proxy: /GeometryProxy/”时出错。我有下面的预览代码。我不知道在占位符中放什么,我很困惑。我已经包含了我的完整代码以供审查。请往下看
struct MathematicallyMainController_Previews: PreviewProvider {
static var previews: some View {
MathematicallyMainController(proxy: // what do i put here?)
}
}
我的完整代码:
这就是 'var' 的问题所在。
struct MathematicallyMainController: View {
@StateObject var tabBarModel = TabBarViewModel()
@Environment(\.colorScheme) var colorScheme
@State var selectedIndex = 0
@State var isSelectedA = false
@State var isSelectedB = false
@State var isSelectedC = false
@State var isSelectedD = false
@State var isSelectedE = false
@State var proxy: GeometryProxy
var body: some View {
ZStack {
let bottomEdge = proxy.safeAreaInsets.bottom
switch selectedIndex {
case 0:
HomeViewController()
case 1:
BrowseView()
case 2:
RewardsView()
case 3:
EssentialsView()
case 4:
SchoolModeView()
default:
HomeViewController()
}
ZStack {
RoundedRectangle(cornerRadius: 15)
.fill(.regularMaterial)
.colorScheme(colorScheme == .dark ? .dark : .light)
HStack(alignment: .center) {
Button {
selectedIndex = 0
} label: {
if selectedIndex == 0 {
ZStack {
Circle()
.blur(radius: 20)
.foregroundColor(.blue)
.frame(width: 60)
.padding([.leading, .trailing], 5)
Image(systemName: "house.fill")
.font(.title)
.foregroundColor(colorScheme == .dark ? .black : .white)
.padding([.leading, .trailing], 5)
}
} else {
Image(systemName: "house.fill")
.font(.title)
.foregroundColor(colorScheme == .dark ? .white : .black)
}
}
Button {
selectedIndex = 1
} label: {
if selectedIndex == 1 {
ZStack {
Circle()
.blur(radius: 20)
.foregroundColor(.indigo)
.frame(width: 60)
.padding(.leading, 15)
Image(systemName: "rectangle.stack.fill")
.font(.title)
.foregroundColor(colorScheme == .dark ? .black : .white)
.padding(.leading, 15)
}
} else {
Image(systemName: "rectangle.stack.fill")
.font(.title)
.foregroundColor(colorScheme == .dark ? .white : .black)
.padding(.leading, 15)
}
}
Button {
selectedIndex = 2
} label: {
if selectedIndex == 2 {
ZStack {
Circle()
.blur(radius: 20)
.foregroundColor(.orange)
.frame(width: 60)
.padding([.trailing, .leading], 15)
Image(systemName: "circle.dotted")
.font(.title)
.foregroundColor(colorScheme == .dark ? .black : .white)
.padding([.trailing, .leading], 15)
}
} else {
Image(systemName: "circle.dotted")
.font(.title)
.foregroundColor(colorScheme == .dark ? .white : .black)
.padding(.trailing, 15)
.padding(.leading, 15)
}
}
Button {
selectedIndex = 3
} label: {
if selectedIndex == 3 {
ZStack {
Circle()
.blur(radius: 20)
.foregroundColor(.green)
.frame(width: 60)
.padding(.trailing, 15)
Image(systemName: "doc.text.image")
.font(.title)
.foregroundColor(colorScheme == .dark ? .black : .white)
.padding(.trailing, 15)
}
} else {
Image(systemName: "doc.text.image")
.font(.title)
.foregroundColor(colorScheme == .dark ? .white : .black)
.padding(.trailing, 15)
}
}
Button {
selectedIndex = 4
} label: {
if selectedIndex == 4 {
ZStack {
Circle()
.blur(radius: 20)
.foregroundColor(.purple)
.frame(width: 60)
.padding([.leading, .trailing], 5)
Image(systemName: "graduationcap.fill")
.font(.title)
.foregroundColor(colorScheme == .dark ? .black : .white)
.padding([.leading, .trailing], 5)
}
} else {
Image(systemName: "graduationcap.fill")
.font(.title)
.foregroundColor(colorScheme == .dark ? .white : .black)
}
}
}
.colorScheme(colorScheme == .dark ? .dark : .light)
.padding(.horizontal)
}
.frame(height: 60)
.shadow(color: .primary, radius: -10)
.shadow(color: .black, radius: 10)
.padding([.horizontal])
.padding(.bottom)
.frame(maxHeight: .infinity, alignment: .bottom)
.modifier(OffsetModifier())
.environmentObject(tabBarModel)
.offset(y: tabBarModel.tabState == .floating ? 0 : bottomEdge)
}
}
}
这是我用来创建滚动动画的 ViewModifier。
struct OffsetModifier: ViewModifier {
@EnvironmentObject var model: TabBarViewModel
func body(content: Content) -> some View {
content
.overlay(
GeometryReader { proxy -> Color in
let minY = proxy.frame(in: .global).minY
DispatchQueue.main.async {
let durationOffset: CGFloat = 35
if minY < model.offset {
if model.offset < 0 && -minY > (model.lastStoredOffset + durationOffset) {
withAnimation(.easeOut.speed(1)) {
model.tabState = .floating
}
model.lastStoredOffset = -model.offset
}
}
if minY > model.offset && -minY < (model.lastStoredOffset + durationOffset) {
withAnimation(.easeOut.speed(1)) {
model.tabState = .expanded
}
model.lastStoredOffset = -model.offset
}
model.offset = minY
}
return Color.clear
}
,alignment: .top
)
}
}
你唯一一次使用 proxy
是在这一行:
let bottomEdge = proxy.safeAreaInsets.bottom
因此,没有理由传递整个 GeometryProxy
-- 您可以传递底部插图。此外,它绝对不需要是 @State
变量——当 View
需要随时间改变其状态时使用 @State
—— 这只是传入的参数.
更改此行:
@State var proxy: GeometryProxy
至:
var bottomInset : CGFloat = 0
因为它有一个默认值,所以你的预览可以变成这样:
static var previews: some View {
MathematicallyMainController()
}
如果你真的想传递一个值(比如,从 View
的父级),你可以这样做:
GeometryReader { proxy in
//other view code...
MathematicallyMainController(bottomInset: proxy.safeAreaInsets.bottom)
//other code...
}
也可以选择将 GeometryReader
移到 MathematicallyMainController
内,但我假设您一开始将它移到外面是有原因的。
综上所述,您似乎有一些可以清理的不必要和未使用的代码。例如,isSelectedA-E
变量中的 none 曾经被使用过。这里可能还有更多可以重构的东西,但不在当前问题的范围内。