我正在尝试制作一个类似于 Slack 应用程序的导航 UI,其中我有一个覆盖菜单导航屏幕的主屏幕。我创建了一个使主屏幕可拖动的 ViewModifier。现在我需要添加功能,以便在蓝色菜单屏幕上点击“主页”时,白色主页 View 动画回到中心。我的想法是在全局 AppState 中跟踪 NavigationState:
enum NavigationSelection {
case menu
case home
}
final class AppState: ObservableObject {
let objectWillChange = PassthroughSubject<Void, Never>()
@Published var currentNavigationSelection: NavigationSelection = .home
}
然后当用户点击“主页”时,让它更新 AppState 的 currentNavigationSelection,并让 Draggable View 根据 currentNavigationSelection 确定其偏移量。我真的不确定这种方法,我很难在新的 SwiftUI 风格中考虑它。任何建议将不胜感激。
View 层次结构如下所示:
var body: some View {
ZStack {
Menu()
HomeTabView()
}
}
并且 HomeTabView 应用了可拖动的 ViewModifier:
struct Slidable: ViewModifier {
@EnvironmentObject var app: AppState
@State private var viewState = SlidableViewDragState.normal.defaultPosition
@State private var currentPosition: SlidableViewDragState = .normal {
didSet {
self.viewState = self.currentPosition.defaultPosition
}
}
func body(content: Content) -> some View {
return content
.frame(minWidth: 0, maxWidth: .infinity, minHeight: 0, maxHeight:
.infinity, alignment: Alignment.topLeading)
.offset(self.viewState)
.animation(.interactiveSpring())
.gesture(
DragGesture()
.onChanged({ (value) in
self.viewState = self.currentPosition.applyXTranslation(x: value.translation.width)
})
.onEnded({ (value) in
if value.translation.width < 0 && self.currentPosition == .normal {
return
}
if abs(value.translation.width) > self.currentPosition.switchThreshold {
self.currentPosition = self.currentPosition.oppositePosition
if self.currentPosition == .menuVisible {
self.app.currentNavigationSelection = .menu
}
} else {
self.viewState = self.currentPosition.defaultPosition
}
})
)
}
}
最佳答案
移动两个 View
您目前如何定义两者的位置?以我有限的经验,我会使用 ZStack
嵌入 HomeView
和 MenuView
。这样您就可以独立移动 View 。
然后您使用一个point
变量作为状态,并使DragGesture
设置point
。然后在拖动结束时确定 point
设置的结束位置。
point
是偏移计算的一部分。您可以使用 .offset(x: point.x)
计算菜单偏移,使用 .offset(x: -Self.maxOffset - Self.minusHomeWidth/2 + point .x)
.
minusHomeWidth
是您在主屏幕上时菜单仍然显示的宽度。
定义点
的最小值和最大值的变量:
static let minOffset: CGFloat = 0
static let maxOffset: CGFloat = UIScreen.main.bounds.width - Self.minusHomeWidth
static let minusHomeWidth: CGFloat = UIScreen.main.bounds.width / 10
然后你可以让它移动到主视图宽度
Button(action: {
self.point = CGPoint(x: Self.maxOffset, y: 0)
}) { Text("Go to Home") }
关于类似于 Slack 的 SwiftUI 导航,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57538560/