Проведите между двумя страницами с помощью инструмента выбора сегментированного стиля в SwiftUI - PullRequest
0 голосов
/ 11 января 2020

У меня есть Picker с .pickerStyle(SegmentedPickerStyle()), чтобы сделать его сегментированным элементом управления. Я хочу, чтобы страницы плавно перемещались между ними, а не заменяли представление с помощью условного выражения.

Вот изображение того, что я сделал до сих пор:

What I have made

Ниже приведен код (контролируемый 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 или хорошая альтернатива, это действительно помогло бы.

Однако, если мне нужно прибегнуть к UIKit с UIViewRepresentable, я не знаю, как бы я реализовал это с SwiftUI.

Ответы [ 3 ]

0 голосов
/ 11 января 2020

Здесь возможен подход (обратите внимание, что для тестирования необходимо использовать Simulator, поскольку Preview не обрабатывает .move переходы правильно)

Демонстрация (только используемые виды заглушки, параметры анимации и перехода могут быть настроенным, но идея остается той же).

Примечание: фон переходного вида должен быть непрозрачным (здесь используется Color.white), в противном случае переходы выглядят ... не хорошо.

SwiftUI move view transition

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))
    }
}
0 голосов
/ 12 января 2020

Эти другие ответы указали мне правильное направление, но код кажется немного многословным или не функционировал должным образом.

Вот что изменилось, чтобы заставить мою работать:

  • Заполнение было добавлено к Picker.
  • Заполнение было удалено с конца VStack.
  • Значение if-else было изменено на 2 if с.
  • Добавлены animation, transition и padding модификаторы для каждого из LogInView и SignInView.

Оригинал:

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))
    }
}
0 голосов
/ 11 января 2020

Вы можете обернуть 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))
    }
...