簡體   English   中英

SwiftUI 僅在一個方向上拖動手勢

[英]SwiftUI DragGesture only in one direction

我希望 SwiftUI DragGesture 僅在手勢處於特定方向(水平/垂直)時啟動。 是否可以?

是的,它是通過將手勢轉換的兩個組件(水平或垂直)之一應用於視圖偏移量。

這是作為ViewModifier實現的這種行為。

struct DraggableModifier : ViewModifier {

    enum Direction {
        case vertical
        case horizontal
    }

    let direction: Direction

    @State private var draggedOffset: CGSize = .zero

    func body(content: Content) -> some View {
        content
        .offset(
            CGSize(width: direction == .vertical ? 0 : draggedOffset.width,
                   height: direction == .horizontal ? 0 : draggedOffset.height)
        )
        .gesture(
            DragGesture()
            .onChanged { value in
                self.draggedOffset = value.translation
            }
            .onEnded { value in
                self.draggedOffset = .zero
            }
        )
    }

}

演示:

struct ContentView: View {

    var body: some View {
        VStack {
            Spacer(minLength: 100)
            HStack {
                Rectangle()
                    .foregroundColor(.green)
                    .frame(width: 100, height: 100)
                    .modifier(DraggableModifier(direction: .vertical))
                Text("Vertical")
            }
            Spacer(minLength: 100)
            Rectangle()
                .foregroundColor(.red)
                .frame(width: 100, height: 100)
                .modifier(DraggableModifier(direction: .horizontal))
            Text(verbatim: "Horizontal")
            Spacer(minLength: 100)
        }
    }
}

結果

在此處輸入圖像描述

相當老的問題,但在其他地方找不到答案。

您可以輕松檢查它是向左滑動還是向右滑動,因為手勢返回其結尾 state,其中包含起始和最終 position。

Text("Hello").gesture(DragGesture(minimumDistance: 100).onEnded { endedGesture in
                if (endedGesture.location.x - endedGesture.startLocation.x) > 0 {
                    print("Left")
                } else {
                    print("Right")
                }
}

如果手勢移動水平移動而不是垂直移動,這只會移動視圖。 isDragging boolean 確保滿足第一個條件后,視圖也會垂直移動。 這不是必需的,但它有助於更平滑的拖動。

@State var dragOffset: CGSize = .zero
@State var isDragging = false

.offset(x: offset.width, y: offset.height)
        .gesture(DragGesture()
                    .onChanged { if abs($0.translation.width) > abs($0.translation.height) || isDragging {
                        self.offset = $0.translation
                        self.isDragging = true
                        
                    }
                    }
                    .onEnded {
                        isDragging = false
                        
                    })

一個例子,在運動開始時,確定垂直或水平運動,之后 object 僅在這個方向上運動

struct Test: View {

    @State private var offsetX = CGFloat.zero
    @State private var offsetY = CGFloat.zero
    
    var body: some View {
        ZStack {
            Divider()
            Divider().rotationEffect(.degrees(90))
            Divider().rotationEffect(.degrees(45))
            Divider().rotationEffect(.degrees(-45))

            VStack {
                Spacer()
                Text("offsetX: \(offsetX)     offsetY: \(offsetY)")
                    .foregroundColor(.black.opacity(0.5))
                    .frame(maxWidth: .infinity)
                    .padding(.bottom, 18.0)
            }
            
            Rectangle()
                .fill(.green)
                .frame(width: 300.0, height: 200.0)
                .cornerRadius(13.0)
                .offset(x: offsetX, y: offsetY)
                .gesture(drag)
        }
    }
    
    @State private var horizontal = true
    @State private var vertical = true
    
    var drag: some Gesture {
        DragGesture()
            .onChanged { dg in
                var x = dg.translation.width
                var y = dg.translation.height
                
                if ((x < 0 && y < 0 && x < y) || (x < 0 && y > 0 && -x > y) || (x > 0 && y < 0 && x > -y) || (x > 0 && y > 0 && x > y)) && self.horizontal && self.vertical {
                    self.horizontal = true
                    self.vertical = false
                } else if vertical && horizontal {
                    self.horizontal = false
                    self.vertical = true
                }
                
                if self.horizontal {
                    self.offsetX = x
                } else {
                    self.offsetY = y
                }
            }
            .onEnded { _ in
                withAnimation {
                    self.offsetX = .zero
                    self.offsetY = .zero
                }
                self.horizontal = true
                self.vertical = true
            }
        
    }
}

演示: https://i.stack.imgur.com/Vdbkx.gif

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM