按下 NavigationLink 时的 SwiftUI 动作

lvo*_*mer 5 user-interface swift swiftui

我在 SwiftUI for Mac 中NavigationView有很多NavigationLinks

每当我按下导航项时,导航详细信息就会显示在右侧。但是,我的活动导航项目有一个自定义样式。当我按下一个项目时,我想调用一个动作。我已经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
         }
Run Code Online (Sandbox Code Playgroud)

日志"Tapped Nav"有时只输出..我认为导航项内的图像和文本有问题。当我点击项目时,有没有更好的方法来调用动作函数?

use*_*734 7

  1. 考虑到该帐户,无需任何“点击”即可以编程方式或从操作菜单等方式激活该导航链接。
  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
}
Run Code Online (Sandbox Code Playgroud)

该工作示例向您展示了如何将其用于“自定义样式”,但这可以扩展到任何用例(请参阅调试窗口上的打印输出)

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()
    }
}
Run Code Online (Sandbox Code Playgroud)

生成的示例应用程序正在运行

在此输入图像描述


Ren*_*ria 6

如果您正在寻找一种更简单的解决方法,一个“不太好”的选择是添加onAppear您将要呈现的块代码:

NavigationView {
        VStack{
        NavigationLink(destination: SecondContentView().onAppear() { // <<-- here
           NSLog("Tapped Nav")        
           self.currentSelected = 0
        }) {
        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))

        }
     }
Run Code Online (Sandbox Code Playgroud)