У меня есть кнопка, которую я хотел бы связать с другим представлением при нажатии на нее. Мне сказали поместить его в NavigationLink, использовать стиль кнопки .borderless, но он активируется за пределами своей области во всей строке списка. Я экспериментировал с использованием представления навигации или отключением навигационной ссылки среди других предложений, но это не решило проблему или просто испортило мое представление, поэтому я, должно быть, делаю что-то не так.
Вот вид элемента списка
struct NodeListItem: View {
var body: some View {
LazyVStack(alignment: .leading) {
//has more information up here I don't think is relevant
HStack {
NavigationLink(destination: UserMessageList(user: node.user!)) {
Button("DM") {
//don't actually need it to do anything besides changing views
}
//.borderless does nothing I want it to have a border
.buttonStyle(.borderedProminent)
}
}
}
}
Вот мой список
struct NodeList: View {
var body: some View {
NavigationStack {
List(nodes, id: \.self) { node in
NodeListItem(node: node)
.contextMenu {
Button {
node.user!.mute = !node.user!.mute
} label: {
Label(node.user!.mute ? "Show DM Alerts" : "Hide DM Alerts", systemImage: node.user!.mute ? "bell" : "bell.slash")
}
if bleManager.connectedPeripheral != nil {
Button (role: .destructive) {
deleteNodeId = node.num
isPresentingDeleteNodeAlert = true
} label: {
Label("Delete Node", systemImage: "trash")
}
}
}
}
.listStyle(.plain)
}
}
Любая помощь/предложения приветствуются!
Разве NavigationLink уже не является своего рода кнопкой? AFAIK, он настроен с использованием пункта назначения навигации и пользовательского интерфейса для него (например, Text для простой текстовой кнопки).





Не следует использовать NavigationLink. Вы должны осуществлять навигацию программно в закрытии действия кнопки.
Предполагая, что тип nodes — [Node], вы можете добавить @State, обозначающий путь навигации, следующим образом:
@State private var path: [Node] = []
let nodes = [...]
var body: some View {
NavigationStack(path: $path) {
List(nodes, id: \.self) { node in
NodeListItem(node: node) {
// programmatic navigation
path.append(node)
}
.contextMenu { ... }
}
.navigationDestination(for: Node.self) { node in
UserMessageList(user: node.user!)
}
}
}
Обратите внимание, что пункт назначения навигации UserMessageList указывается на List, а не на каждом отдельном NodeListItem.
NodeListItem следует изменить, чтобы он закрывал действие кнопки:
struct NodeListItem: View {
let node: Node
let buttonAction: () -> Void
var body: some View {
LazyVStack(alignment: .leading) {
// ...
HStack {
// ...
Button("DM") {
buttonAction()
}
.buttonStyle(.borderedProminent)
}
}
}
}
Конечно, вы также можете передать @Binding пути навигации и сделать path.append в NodeListItem:
struct NodeListItem: View {
let node: Node
@Binding var path: [Node]
var body: some View {
LazyVStack(alignment: .leading) {
// ...
HStack {
// ...
Button("DM") {
path.append(node)
}
.buttonStyle(.borderedProminent)
}
}
}
}
// ...
NodeListItem(node: node, path: $path)
Лично я считаю, что первое имеет больше смысла.
По какой-то причине мне не удалось добавить такой узел в NodeListItem, и компилятор сообщил мне, что не может проверить выражение, возможно, что-то не так с моей стороны. Но метод @binding сработал! Большое спасибо! просто интересно, если в будущем список будет состоять из 100+ элементов, возникнут ли проблемы с производительностью или сможет ли приложение справиться с таким большим количеством путей, но я думаю слишком далеко вперед. Спасибо!
NavigationLink сам по себе является кнопкой, и обычно его можно стилизовать с помощью .buttonStyle так же, как и обычный Button. Причина, по которой здесь это не работает, заключается в том, что этот элемент является записью в List.
Однако, если вы создадите стиль метки NavigationLink самостоятельно, вы сможете избежать вложенной кнопки. Что-то вроде этого:
NavigationLink {
UserMessageList(user: node.user!)
} label: {
Text("DM")
.padding(.horizontal, 12)
.padding(.vertical, 7)
.foregroundStyle(.white)
.background(
RoundedRectangle(cornerRadius: 6)
.fill(.link)
)
}
Строка списка по-прежнему имеет стрелку сбоку, и навигация происходит при нажатии на строку в любом месте. Если это проблема, которую вы пытаетесь решить, то, вероятно, лучше не использовать NavigationLink → см. ответ Sweeper для получения подробной информации о том, как вместо этого программно перемещаться.
Что вы можете попробовать сделать, так это поместить свою навигационную ссылку и кнопку в Zstack, кнопка находится вверху навигационной ссылки.