Быстрый свайп / перетаскивание по ссылке навигации

#swift #swiftui #iso #navigationview #swiftui-navigationlink

#swift #swiftui #iso #navigationview #swiftui-navigationlink

Вопрос:

Я хочу иметь возможность обновлять представление, проводя пальцем влево / вправо по NavigationView, в котором есть несколько навигационных ссылок. Навигационные ссылки ведут к различным представлениям презентации.

Когда я начинаю жест перетаскивания на самом внешнем виде, если этот жест начинается с ссылки навигации, ссылка меняет цвет, как если бы она была нажата. Продолжая жест перетаскивания, основной вид обновляется, как и ожидалось, и ссылка навигации возвращается в свое обычное состояние (цвет).

Мне нужен способ, чтобы NavigationLink НЕ менял цвет, когда происходит жест перетаскивания. Может быть, способ заставить NavigationLink реагировать «если» касание — это долгое касание или что-то в этом роде.

Вот некоторый код, который демонстрирует то, что я вижу. Это не мой реальный проект, а очень урезанный пример.

Любые предложения или решения приветствуются!

 import SwiftUI

struct ContentView: View {
    
    @State var outputText: String = ""
    var body: some View {
        VStack(alignment: .center, spacing: 20) {
            NavigationView {
                VStack {
                    Text("Navigation View")
                    NavigationLink(destination: Text("Showwing Widget")) {
                        HStack {
                            Text("Navigation Link")
                        }
                        .frame(width: 300, height: 200)
                        .border(Color.blue)
                    }
                    .border(Color.red)
                    Spacer()
                }
                .border(Color.yellow)
            }

            Text(outputText)
                .font(.title)
                .fontWeight(.bold)

            Text("My Green Oval")
                .foregroundColor(.white)
                .fontWeight(.bold)
                .font(.title)
                .frame(width: 300, height: 200)
                .background(
                    Ellipse()
                        .fill(Color.green)
                )
            Button(action: {
                outputText = "Button tapped"
            }) {
                Text("Button to Tap")
            }
            
            Text("Just some words...")
            Spacer()
        }
        .highPriorityGesture(DragGesture(minimumDistance: 25, coordinateSpace: .local)
            .onEnded { value in
                if abs(value.translation.height) < abs(value.translation.width) {
                    if abs(value.translation.width) > 50.0 {
                        if value.translation.width < 0 {
                            self.swipeRightToLeft()
                        } else if value.translation.width > 0 {
                            self.swipeLeftToRight()
                        }
                    }
                }
            }
        )
    }
    
    func swipeRightToLeft() {
        outputText = "Swiped Right to Left <--"
    }
    
    func swipeLeftToRight() {
        outputText = "Swiped Left to Right -->"
    }
}

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

 

Ответ №1:

После бесконечных игр у меня есть решение! Может быть, это хакерство, но оно работает без особых усилий. Настройте свой вид со смещением, зависящим от того, открыта строка вашего ящика или нет, а также создайте переменную состояния, чтобы отслеживать, перетаскивает ли ваш пользователь. Вы можете получить ширину экрана с помощью UIScreen.main.bounds .ширина.

 .offset(x: self.isOpen ? -screenWidth/12 : 0, y: 0)
                .simultaneousGesture(DragGesture()
                            .onChanged{ gesture in
                                self.isDragging = true
                                self.offset = gesture.translation.width
                            }
                            .onEnded { _ in
                                self.isDragging = false
                                if self.offset > 0 {
                                    withAnimation {
                                        self.isOpen = false
                                        self.offset = 0
                                    }
                                } else if self.offset < 0 {
                                    withAnimation {
                                        self.isOpen = true
                                        self.offset = 0
                                    }
                                }
                            })
 

Затем добавьте этот модификатор отключения в свою навигационную ссылку

 .disabled(self.isDragging || self.isOpen)
 

Удачи! Надеюсь, это сработает и для вас, если вы не нашли решения.