簡體   English   中英

SwiftUI:使用 LongPressGesture 顯示類似 Pinterest 的上下文菜單

[英]SwiftUI: Using LongPressGesture to display a Pinterest like context menu

我正在嘗試在他們的 iOS 應用程序中創建一個類似於 Pinterest 上下文菜單的上下文菜單。 長按一個帖子會顯示一個四按鈕視圖,當用戶繼續長按時,可以拖動其他按鈕 select。 讓 go 長按將 select 您當前選擇的任何按鈕或完全關閉菜單,如果您沒有選擇任何內容。 請參閱下面的示例:

pinterest 上下文菜單

到目前為止,我在這里嘗試過類似於 Apple 文檔的內容: https://developer.apple.com/documentation/swiftui/longpressgesture

但似乎手勢一旦達到手勢中定義的 minimumDuration 就結束了。 只要用戶按住,我希望手勢繼續,一旦他們讓 go 結束。

此外,當涉及到拖動和選擇其他按鈕時,我感到很困惑。 到目前為止,這是我的方法:

struct Example: View {

@GestureState var isDetectingLongPress = false
@State var completedLongPress = false

var longPress: some Gesture {
    LongPressGesture(minimumDuration: 3)
        .updating($isDetectingLongPress) { currentState, gestureState,
                transaction in
            gestureState = currentState
            transaction.animation = Animation.easeIn(duration: 2.0)
        }
        .onEnded { finished in
            self.completedLongPress = finished
        }
}

var body: some View {
    
    HStack {
        
        Spacer()
        ZStack {
            // Three button array to fan out when main button is being held
            Button(action: {
                // ToDo
            }) {
                Image(systemName: "circle.fill")
                    .frame(width: 70, height: 70)
                    .foregroundColor(.red)
            }
            .offset(x: self.isDetectingLongPress ? -90 : 0, y: self.isDetectingLongPress ? -90 : 0)
            Button(action: {
                // ToDo
            }) {
                Image(systemName: "circle.fill")
                    .frame(width: 70, height: 70)
                    .foregroundColor(.green)
            }
            .offset(x: 0, y: self.isDetectingLongPress ? -120 : 0)
            Button(action: {
                // ToDo
            }) {
                Image(systemName: "circle.fill")
                    .frame(width: 70, height: 70)
                    .foregroundColor(.blue)
            }
            .offset(x: self.isDetectingLongPress ? 90 : 0, y: self.isDetectingLongPress ? -90 : 0)
            
            // Main button
            Image(systemName: "largecircle.fill.circle")
                .gesture(longPress)
            
        }
        Spacer()
    }

}

我能找到的最接近的等價物是上下文菜單Src:AppleDeveloper

如果你按住,你會得到類似的效果。

上下文菜單 - Apple 開發者文檔

更新:我找到了一個可行的解決方案,但它使用的是 UIKit 因為我不相信 SwiftUI 提供了一種本機執行此操作的方法。 我遵循了此處找到的類似問題的答案的指導: https://stackoverflow.com/a/31591162/862561

但是它是用 ObjC 編寫的,所以我大致翻譯為 Swift。 對於那些好奇的人,這里是該過程的簡化版本:

class UIControlsView: UIView {

let createButton = CreateButtonView()
let secondButton = ButtonView(color: .red)
var currentDraggedButton: ButtonView!

required init?(coder: NSCoder) {
    fatalError("-")
}

init() {
    super.init(frame: .zero)
    self.backgroundColor = .green
    
    let longPress = UILongPressGestureRecognizer(target: self, action: #selector(self.longPress))
    createButton.addGestureRecognizer(longPress)
    createButton.frame = CGRect(x: 0, y: 0, width: 80, height: 80)
    createButton.center = CGPoint(x: UIScreen.main.bounds.size.width / 2, y: 40)
    
    secondButton.frame = CGRect(x: 0, y: 0, width: 80, height: 80)
    secondButton.center = CGPoint(x: UIScreen.main.bounds.size.width / 2, y: 40)

    self.addSubview(secondButton)
    self.addSubview(createButton)
}

@objc func longPress(sender: UILongPressGestureRecognizer) {
    if sender.state == .began {
        print("Started Long Press")
        secondButton.center.x = secondButton.center.x + 90
    }
    
    if sender.state == .changed {
        let location = sender.location(in: self)
        guard let superViewLocation = self.superview?.convert(location, from: self) else {
            return
        }

        guard let view = self.superview?.hitTest(superViewLocation, with: nil) else {
            return
        }

        if view.isKind(of: ButtonView.self) {
            let touchedButton = view as! ButtonView
            
            if self.currentDraggedButton != touchedButton {
                if self.currentDraggedButton != nil {
                    self.currentDraggedButton.untouchedUp()
                }
            }
            
            self.currentDraggedButton = touchedButton
            touchedButton.isTouchedUp()
        } else {
            if self.currentDraggedButton != nil {
                print("Unsetting currentDraggedButton")
                self.currentDraggedButton.untouchedUp()
            }
        }
    }
    
    if sender.state == .ended {
        print("Long Press Ended")
        let location = sender.location(in: self)
        guard let superViewLocation = self.superview?.convert(location, from: self) else {
            return
        }

        guard let view = self.superview?.hitTest(superViewLocation, with: nil) else {
            return
        }
        
        if view.isKind(of: ButtonView.self) {
            let touchedButton = view as! ButtonView
            
            touchedButton.untouchedUp()
            touchedButton.tap()
            self.currentDraggedButton = nil
        }

        secondButton.center.x = secondButton.center.x - 90
    }
    
}

暫無
暫無

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

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