SwitUI - две навигационные ссылки в списке

У меня две ссылки NavigationLink в ячейке моего списка

Я хочу перейти в пункт назначения1, когда я коснусь один раз, и перейти в пункт назначения2, когда я коснусь дважды. Поэтому я добавил два жеста касания для управления навигацией.

Но когда я нажимаю, возникают два вопроса:

  • 1 Блок жестов касания не вызывается.
  • 2 Две навигационные ссылки будут активированы автоматически, даже если они находятся за TextView. Реальный эффект таков: нажмите на ячейку - ›перейти к пункту назначения1-› вернуться домой - ›перейти к пункту назначения2 -› вернуться домой

Вот мой код:

struct MultiNavLink: View {
    @State var mb_isActive1 = false;
    @State var mb_isActive2 = false;
    
    var body: some View {
        return
            NavigationView {
                List {
                    ZStack {
                        NavigationLink("", destination: Text("Destination1"), isActive: $mb_isActive1)
                        NavigationLink("", destination: Text("Destination2"), isActive: $mb_isActive2)
                        Text("Single tap::go to destination1\nDouble tap,go to destination2")
                    }
                    .onTapGesture(count: 2, perform: {()->Void in
                        NSLog("Double tap::to destination2")
                        self.mb_isActive2 = true
                    }).onTapGesture(count: 1, perform: {()->Void in
                        NSLog("Single tap::to destination1")
                        self.mb_isActive1 = true
                    })
                }.navigationBarTitle("MultiNavLink",displayMode: .inline)
        }
    }
}

Я попытался удалить элемент List, и все идет так, как я ожидал. Кажется, что все странно из-за элемента List.

Я нашел этот вопрос: SwiftUI - две кнопки в списке, но ситуация отличается от меня.

Жду вашего ответа, большое спасибо ...


person BinaryBang    schedule 20.08.2020    source источник
comment
Я считаю, что ваша архитектура неправильная. Попробуйте удалить ZStack и NavigationLink из List и заменить на Button, затем примените модификаторы .onTapGesture к Button, встраивая NavLinks в код perform для каждого.   -  person andrewbuilder    schedule 20.08.2020


Ответы (2)


Попробуйте следующий подход - идея состоит в том, чтобы скрыть ссылки на фоне видимого контента и сделать их неактивными для пользовательского интерфейса, но активировать программно.

Протестировано с Xcode 12 / iOS 14.

struct MultiNavLink: View {

    var body: some View {
        return
            NavigationView {
                List {
                    OneRowView()
                }.navigationBarTitle("MultiNavLink", displayMode: .inline)
        }
    }
}

struct OneRowView: View {
    @State var mb_isActive1 = false
    @State var mb_isActive2 = false

    var body: some View {
        ZStack {
            Text("Single tap::go to destination1\nDouble tap,go to destination2")
        }
        .frame(maxWidth: .infinity, maxHeight: .infinity)
        .contentShape(Rectangle())
        .background(Group {
            NavigationLink(destination: Text("Destination1"), isActive: $mb_isActive1) {
                    EmptyView() }
                .buttonStyle(PlainButtonStyle())
            NavigationLink(destination: Text("Destination2"), isActive: $mb_isActive2) {
                    EmptyView() }
                .buttonStyle(PlainButtonStyle())
        }.disabled(true))
        .highPriorityGesture(TapGesture(count: 2).onEnded {
            self.mb_isActive2 = true
        })
        .onTapGesture(count: 1) {
            self.mb_isActive1 = true
        }
    }
}
person Asperi    schedule 20.08.2020
comment
Это решение идеально соответствует моим потребностям. Наконец, я обнаружил, что когда ячейка списка содержит несколько ссылок навигации, вы нажимаете ячейку один раз, все ссылки навигации будут активированы. Ключевой момент установлен им disable(true), и каждая отдельная навигационная ссылка активна с помощью другой отдельной логики. - person BinaryBang; 20.08.2020
comment
@ Аспери, я уверен, что ты гений - person Markus Proctor; 26.08.2020

У ссылки навигации есть инициализатор, который принимает привязку selection, и всякий раз, когда для этого selection установлено значение NavigationLink tag, ссылка навигации срабатывает. В качестве подсказки, если приложение не может различать и идентифицировать ваши касания, и даже при двух касаниях, действие для одного касания все равно будет запущено, тогда вы можете использовать модификатор одновременного жеста (.simultaneousGesture()) вместо обычного жеста ( .gesture()) модификатор.

struct someViewName: View {
    
    @State var navigationLinkTriggererForTheFirstOne: Bool? = nil
    @State var navigationLinkTriggererForTheSecondOne: Bool? = nil
    
    var body: some View {
        VStack {
            NavigationLink(destination: SomeDestinationView(),
                           tag: true,
                           selection: $navigationLinkTriggererForTheFirstOne) {
                EmptyView()
            }
            
            NavigationLink(destination: AnotherDestinationView(),
                           tag: true,
                           selection: $navigationLinkTriggererForTheSecondOne) {
                EmptyView()
            }
            
            NavigationView {
                    Button("tap once to trigger the first navigation link.\ntap twice to trigger the second navigation link.") {
                        // tap once
                        self.navigationLinkTriggererForTheFirstOne = true
                    }
                    .simultaneousGesture(
                        TapGesture(count: 2)
                            .onEnded { _ in
                                self.navigationLinkTriggererForTheSecondOne = true
                            }
                    )
            }
        }
    }
}
person Mahdi BM    schedule 20.08.2020
comment
Этот элемент хорошо работает, когда я использую его без элемента списка. Но когда я помещаю элемент в список, нажимаю на него, и он также работает не так, как мы ожидали. - person BinaryBang; 20.08.2020