如何在SwiftUI中将NavigationLink显示为按钮

时间:2019-07-21 06:32:12

标签: navigation swiftui

我在这里已经阅读了很多有关SwiftUI中导航的信息,并尝试了几件事,但是没有任何工作如预期的那样。

基本上,我有一个包含锻炼列表的视图,您可以通过单击一行来显示一个锻炼。可以将NavigationView和NavigationLink一起使用。

现在,我希望详细视图上的按钮开始锻炼。这应该打开一个带有计时器的视图。该视图应显示与详细视图相同的动画,并在导航栏中使用后退按钮显示锻炼的名称。

我可以在详细信息页面上的NavigationLink视图中实现此功能,但是该链接始终显示为全宽行,并在右侧显示箭头。我希望将它改为一个按钮,但NavigationLink似乎可以抵抗样式。

struct WorkoutDetail: View {
    var workout: Workout

    var body: some View {
        VStack {
            NavigationLink(destination: TimerView()) {
                Text("Starten")
            }.navigationBarTitle(Text(workout.title))
        }
    }
}

struct WorkoutList: View {
    var workoutCollection: WorkoutCollection

    var body: some View {
        NavigationView {
            List(workoutCollection.workouts) { workout in
                NavigationLink(destination: WorkoutDetail(workout: workout)) {
                    WorkoutRow(workout: workout)
                }
            }.navigationBarTitle(Text("Workouts"))
        }
    }
}

已更新:以下屏幕截图说明了我的意思:

enter image description here

8 个答案:

答案 0 :(得分:10)

从Beta 6开始,您无需将视图包装在NavigationLink内,以使其在按下时触发导航。

我们可以仅将属性与NavigationLink绑定在一起,只要我们更改该属性,无论执行什么操作,导航都会触发。 例如-

struct SwiftUI: View {
    @State private var action: Int? = 0

    var body: some View {

        NavigationView {
                    VStack {
                        NavigationLink(destination: Text("Destination"), tag: 1, selection: $action) {
                            EmptyView()
                        }


                        Text("Your Custom View")
                            .onTapGesture {
                 //perform some tasks if needed before opening Destination view
                                self.action = 1
                        }
                    }
                }
        }
}

就这么简单。只要您更改Bindable属性的值(即操作),NavigationLink就会将其tag的预定义值与绑定的属性action(如果两者相等)进行比较导航发生。

因此,您可以使用任何方式创建视图,并且无论采取任何操作,都可以从任何视图触发导航,只需使用绑定了NavigationLink的属性即可。

谢谢,希望对您有所帮助。

答案 1 :(得分:7)

例如,我认为准确的方法是使用buttonStyle

NavigationLink(destination: WorkoutDetail(workout: workout)) {
  WorkoutRow(workout: workout)
}
.buttonStyle(ButtonStyle3D(background: Color.yellow))

答案 2 :(得分:5)

Pankaj Bhalala的解决方案非常相似,但是删除了ZStack:

struct ContentView: View {
    @State var selectedTag: String?

    var body: some View {
        Button(action: {
            self.selectedTag = "xx"
        }, label: {
            Image(systemName: "plus")
        })
        .background(
            NavigationLink(
                destination: Text("XX"),
                tag: "xx",
                selection: $selectedTag,
                label: { EmptyView() }
            )
        )
    }
}

等待一个没有状态的更简洁的解决方案。你呢?

答案 3 :(得分:3)

您可以将NavigationLink用作ZStack的按钮:

@State var tag:Int? = nil
ZStack {
  NavigationLink(destination: MyModal(), tag: 1, selection: $tag) {
    EmptyView()
  }

  Button(action: {
    self.tag = 1
  }, label: {
    Text("show view tag 1")
  })
}

希望这会有所帮助。

答案 4 :(得分:1)

我不知道为什么所有这些答案都使事情变得如此复杂。在SwiftUI 2.0中,您只需在导航链接的内部 中添加按钮!

NavigationLink(destination: TimerView()) {
    Text("Starten")
}

您可以将SwiftUI样式应用于Text对象,就像对任何其他元素进行样式设置一样。

答案 5 :(得分:0)

您可以将导航链接直接添加到按钮,如下所示:

if issubclass(e, connector.errors.Error):
    # do error handling for mysql related errors
else:
    # do error handling for other errors

答案 6 :(得分:-1)

使用按钮标签内的NavigationLink。

Button(action: {
    print("Floating Button Click")
}, label: {
    NavigationLink(destination: AddItemView()) {
         Text("Open View")
     }
})

答案 7 :(得分:-3)

Xcode 11 Beta 5终于解决了这个问题,所以这是一个错误。