Действие SwiftUI при нажатии на NavigationLink - PullRequest
2 голосов
/ 17 февраля 2020

У меня есть NavigationView с множеством NavigationLinks в SwiftUI для Ma c.

Каждый раз, когда я нажимаю элемент навигации, справа отображается деталь навигации. Тем не менее, у меня есть собственный стиль для моих активных элементов навигации. Когда я нажимаю пункт, я хочу вызвать действие. Я пробовал функцию onTapGesture() на NavigationLink, однако она работает неправильно / как ожидалось.

Вот мой код:

 NavigationView {
        VStack{

            NavigationLink(destination: SecondContentView()) {
            VStack
            {
                Image("Calendar")
                    .resizable().frame(width:40, height: 40)
                    .colorMultiply(currentSelected == 0 ? Color(red: 57 / 255, green: 214 / 255, blue: 155 / 255) : Color(red: 255 / 255, green: 255 / 255, blue: 255 / 255))
                Text("Dates")
                    .foregroundColor(currentSelected == 0 ? Color(red: 57 / 255, green: 214 / 255, blue: 155 / 255) : Color(red: 255 / 255, green: 255 / 255, blue: 255 / 255))

            }
         }
         .buttonStyle(PlainButtonStyle())
         .padding(18)
         .background(currentSelected == 0 ? Color(.controlBackgroundColor) : Color(.clear))
         .zIndex(50)
         .onTapGesture {
            NSLog("Tapped Nav")
            self.currentSelected = 0
         }

Журнал "Tapped Nav" иногда выводится только ... Я думаю, что есть проблема с изображением и текстом, который находится внутри элемента навигации. Есть ли лучший способ вызвать функцию действия, когда я нажимаю на элемент?

1 Ответ

2 голосов
/ 17 февраля 2020
  1. Примите во внимание, что навигационная ссылка может быть активирована без какого-либо «касания», программно или из меню действий и т. Д. c.
  2. Если у вас более одной навигационной ссылки, используйте правильный инициализатор, который дает вам возможность делать то, что вы хотите сделать

В настоящее время у нас есть три разных инициализатора, особенно третий может помочь в вашем случае.

/// A view that controls a navigation presentation.
@available(iOS 13.0, OSX 10.15, tvOS 13.0, watchOS 6.0, *)
public struct NavigationLink<Label, Destination> : View where Label : View, Destination : View {

    /// Creates an instance that presents `destination`.
    public init(destination: Destination, @ViewBuilder label: () -> Label)

    /// Creates an instance that presents `destination` when active.
    public init(destination: Destination, isActive: Binding<Bool>, @ViewBuilder label: () -> Label)

    /// Creates an instance that presents `destination` when `selection` is set
    /// to `tag`.
    public init<V>(destination: Destination, tag: V, selection: Binding<V?>, @ViewBuilder label: () -> Label) where V : Hashable

    /// Declares the content and behavior of this view.
    public var body: some View { get }

    /// The type of view representing the body of this view.
    ///
    /// When you create a custom view, Swift infers this type from your
    /// implementation of the required `body` property.
    public typealias Body = some View
}

В рабочем примере показано, как использовать его для «пользовательского стиля», но это может быть расширено для любого варианта использования (см. Распечатку в окне отладки).

import SwiftUI

class Model: ObservableObject {
    @Published var selection: Int? {
        willSet {
            if let nv = newValue {
                selected = nv
                willChangeSelection?(selected)
            }
        }
    }
    var selected: Int = 0
    let willChangeSelection: ((Int) -> Void)?
    init( onSelection: ((Int)->Void)? ) {
        willChangeSelection = onSelection
        selection = 1
    }
}

struct ContentView: View {
    @ObservedObject var model = Model { i in
        print("selected:", i)
    }
    var body: some View {

        NavigationView {
            List {
                NavigationLink(destination: Detail(txt: "First"), tag: 1, selection: $model.selection) {
                    RowLabel(txt: "First", tag: 1, selected: model.selected)
                }
                NavigationLink(destination: Detail(txt: "Second"), tag: 2, selection: $model.selection) {
                    RowLabel(txt: "Second", tag: 2, selected: model.selected)
                }
                NavigationLink(destination: Detail(txt: "Third"), tag: 3, selection: $model.selection) {
                    RowLabel(txt: "Third", tag: 3, selected: model.selected)
                }
            }
            .frame(width: 200, height: 300)
            Detail(txt: "First")
        }.frame(width: 500)
    }
}

struct Detail: View {
    let txt: String
    var body: some View {
        VStack {
            Text(self.txt).font(.largeTitle)
        }.frame(width: 300)
    }
}

struct RowLabel: View {
    let txt: String
    let tag: Int
    let selected: Int
    var body: some View {
        Text(txt)
            .font(selected == tag ? .largeTitle: .footnote).padding(.leading, 10)
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

Полученный пример приложения в действии

enter image description here

...