在 SwiftUI 中使用 Segmented-style Picker 在两个页面之间滑动
Swipe between two pages with Segmented-style Picker in SwiftUI
我有一个 Picker
和 .pickerStyle(SegmentedPickerStyle())
使其成为分段控件。我想让页面之间平滑滑动,而不是使用条件语句替换视图。
这是我到目前为止制作的 gif:
这是目前的代码(由 if
控制,而不是在不同页面之间切换):
struct AuthView: View {
@State private var authPath = 0
/* ... */
var body: some View {
VStack {
Picker(selection: $authPath, label: Text("Authentication Path")) {
Text("Log In").tag(0)
Text("Sign Up").tag(1)
}
.pickerStyle(SegmentedPickerStyle())
Spacer()
if authPath == 0 {
LogInView(/* ... */)
} else {
SignUpView(/* ... */)
}
Spacer()
}
.padding()
.background(Color("Color.Background").edgesIgnoringSafeArea(.all))
}
}
我想要类似于 UIPageViewController
的东西。如果有 SwiftUI 版本或好的替代版本,那将非常有帮助。
但是,如果我确实需要借助 UIViewRepresentable
来使用 UIKit,我不知道如何使用 SwiftUI 来实现它。
您可以将 LoginView
和 SignupView
包裹在某个容器中以使其具有动画效果。
var body: some View {
VStack {
Picker(selection: $authPath, label: Text("Authentication Path")) {
// withAnimation(Animation.easeInOut.speed(0.5)){
Text("Log In").tag(0)
Text("Sign Up").tag(1)}
//}
.pickerStyle(SegmentedPickerStyle())
Spacer()
if authPath == 0 {
NavigationView{
Text("1")
}.animation(.default).transition(.move(edge: .leading))
//(/* ... */)
} else {
NavigationView{
Text("2")
}.animation(.default).transition(.move(edge: .leading))
//(/* ... */)
}
Spacer()
}
.padding()
.background(Color("Color.Background").edgesIgnoringSafeArea(.all))
}
这是可能的方法(请注意,为了测试它需要使用模拟器,因为预览无法正确处理 .move
转换)
Demo(只是用stub views,动画和transition的参数可以配置,但是思路还是一样的)
注意:转换视图的背景应该是不透明的(这里使用 Color.white
),否则转换看起来...不太好。
struct TestTwoViewMoveIn: View {
@State private var authPath: Int? = nil
/* ... */
var body: some View {
VStack {
Picker(selection: Binding<Int>(
get: { self.authPath ?? 0 },
set: { tag in
withAnimation { // needed explicit for transitions
self.authPath = tag
}
}),
label: Text("Authentication Path")) {
Text("Log In").tag(0)
Text("Sign Up").tag(1)
}
.pickerStyle(SegmentedPickerStyle())
Spacer()
ZStack {
Rectangle().fill(Color.clear)
if nil == authPath {
LogInView(/* ... */)
.background(Color.white) // << set your background
}
if authPath == 0 {
LogInView(/* ... */)
.background(Color.white) // << set your background
.transition(.move(edge: .leading))
}
if authPath == 1 {
SignUpView(/* ... */)
.background(Color.white) // << set your background
.transition(.move(edge: .trailing))
}
}
Spacer()
}
.padding()
.background(Color("Color.Background").edgesIgnoringSafeArea(.all))
}
}
这些其他答案为我指明了正确的方向,但代码似乎有点冗长或未按预期运行。
以下是使我的工作正常进行的更改:
- 填充已添加到
Picker
。
- 已删除
VStack
末尾的填充。
if-else
改为 2 if
s.
- 为
LogInView
和 SignInView
添加了 animation
、transition
和 padding
修饰符。
原文:
struct AuthView: View {
@State private var authPath = 0
/* ... */
var body: some View {
VStack {
Picker(selection: $authPath, label: Text("Authentication Path")) {
Text("Log In").tag(0)
Text("Sign Up").tag(1)
}
.pickerStyle(SegmentedPickerStyle())
Spacer()
if authPath == 0 {
LogInView(/* ... */)
} else {
SignUpView(/* ... */)
}
Spacer()
}
.padding()
.background(Color("Color.Background").edgesIgnoringSafeArea(.all))
}
}
新:
struct AuthView: View {
@State private var authPath = 0
/* ... */
var body: some View {
VStack {
Picker(selection: $authPath, label: Text("Authentication Path")) {
Text("Log In").tag(0)
Text("Sign Up").tag(1)
}
.pickerStyle(SegmentedPickerStyle())
.padding()
Spacer()
if authPath == 0 {
LogInView(/* ... */)
.animation(.default)
.transition(.move(edge: .leading))
.padding()
}
if authPath == 1 {
SignUpView(/* ... */)
.animation(.default)
.transition(.move(edge: .trailing))
.padding()
}
Spacer()
}
.background(Color("Color.Background").edgesIgnoringSafeArea(.all))
}
}
我有一个 Picker
和 .pickerStyle(SegmentedPickerStyle())
使其成为分段控件。我想让页面之间平滑滑动,而不是使用条件语句替换视图。
这是我到目前为止制作的 gif:
这是目前的代码(由 if
控制,而不是在不同页面之间切换):
struct AuthView: View {
@State private var authPath = 0
/* ... */
var body: some View {
VStack {
Picker(selection: $authPath, label: Text("Authentication Path")) {
Text("Log In").tag(0)
Text("Sign Up").tag(1)
}
.pickerStyle(SegmentedPickerStyle())
Spacer()
if authPath == 0 {
LogInView(/* ... */)
} else {
SignUpView(/* ... */)
}
Spacer()
}
.padding()
.background(Color("Color.Background").edgesIgnoringSafeArea(.all))
}
}
我想要类似于 UIPageViewController
的东西。如果有 SwiftUI 版本或好的替代版本,那将非常有帮助。
但是,如果我确实需要借助 UIViewRepresentable
来使用 UIKit,我不知道如何使用 SwiftUI 来实现它。
您可以将 LoginView
和 SignupView
包裹在某个容器中以使其具有动画效果。
var body: some View {
VStack {
Picker(selection: $authPath, label: Text("Authentication Path")) {
// withAnimation(Animation.easeInOut.speed(0.5)){
Text("Log In").tag(0)
Text("Sign Up").tag(1)}
//}
.pickerStyle(SegmentedPickerStyle())
Spacer()
if authPath == 0 {
NavigationView{
Text("1")
}.animation(.default).transition(.move(edge: .leading))
//(/* ... */)
} else {
NavigationView{
Text("2")
}.animation(.default).transition(.move(edge: .leading))
//(/* ... */)
}
Spacer()
}
.padding()
.background(Color("Color.Background").edgesIgnoringSafeArea(.all))
}
这是可能的方法(请注意,为了测试它需要使用模拟器,因为预览无法正确处理 .move
转换)
Demo(只是用stub views,动画和transition的参数可以配置,但是思路还是一样的)
注意:转换视图的背景应该是不透明的(这里使用 Color.white
),否则转换看起来...不太好。
struct TestTwoViewMoveIn: View {
@State private var authPath: Int? = nil
/* ... */
var body: some View {
VStack {
Picker(selection: Binding<Int>(
get: { self.authPath ?? 0 },
set: { tag in
withAnimation { // needed explicit for transitions
self.authPath = tag
}
}),
label: Text("Authentication Path")) {
Text("Log In").tag(0)
Text("Sign Up").tag(1)
}
.pickerStyle(SegmentedPickerStyle())
Spacer()
ZStack {
Rectangle().fill(Color.clear)
if nil == authPath {
LogInView(/* ... */)
.background(Color.white) // << set your background
}
if authPath == 0 {
LogInView(/* ... */)
.background(Color.white) // << set your background
.transition(.move(edge: .leading))
}
if authPath == 1 {
SignUpView(/* ... */)
.background(Color.white) // << set your background
.transition(.move(edge: .trailing))
}
}
Spacer()
}
.padding()
.background(Color("Color.Background").edgesIgnoringSafeArea(.all))
}
}
这些其他答案为我指明了正确的方向,但代码似乎有点冗长或未按预期运行。
以下是使我的工作正常进行的更改:
- 填充已添加到
Picker
。 - 已删除
VStack
末尾的填充。 if-else
改为 2if
s.- 为
LogInView
和SignInView
添加了animation
、transition
和padding
修饰符。
原文:
struct AuthView: View {
@State private var authPath = 0
/* ... */
var body: some View {
VStack {
Picker(selection: $authPath, label: Text("Authentication Path")) {
Text("Log In").tag(0)
Text("Sign Up").tag(1)
}
.pickerStyle(SegmentedPickerStyle())
Spacer()
if authPath == 0 {
LogInView(/* ... */)
} else {
SignUpView(/* ... */)
}
Spacer()
}
.padding()
.background(Color("Color.Background").edgesIgnoringSafeArea(.all))
}
}
新:
struct AuthView: View {
@State private var authPath = 0
/* ... */
var body: some View {
VStack {
Picker(selection: $authPath, label: Text("Authentication Path")) {
Text("Log In").tag(0)
Text("Sign Up").tag(1)
}
.pickerStyle(SegmentedPickerStyle())
.padding()
Spacer()
if authPath == 0 {
LogInView(/* ... */)
.animation(.default)
.transition(.move(edge: .leading))
.padding()
}
if authPath == 1 {
SignUpView(/* ... */)
.animation(.default)
.transition(.move(edge: .trailing))
.padding()
}
Spacer()
}
.background(Color("Color.Background").edgesIgnoringSafeArea(.all))
}
}