Swift Pangesture:管理约束:在新锅上闪烁的问题

发布于 2025-02-04 16:37:40 字数 2942 浏览 1 评论 0原文

这是用于控制具有PAN功能视图的视图的代码。

import UIKit

class ViewController: UIViewController {

    @IBOutlet weak var redRect: PaletteView!
    @IBOutlet var paletteTop : NSLayoutConstraint?
    @IBOutlet var paletteLeading : NSLayoutConstraint?
    
    override func viewDidLoad() {
        super.viewDidLoad()
        addRedViewUI(tgt: redRect!)
        redRect.addGestureRecognizer(UIPanGestureRecognizer(target: self, action: #selector(palettePan(_:))))
        redRect?.translatesAutoresizingMaskIntoConstraints = false
        NSLayoutConstraint.activate(paletteConstraints())
    }
    
    func addRedViewUI(tgt : PaletteView) {
        var pos = CGPoint(x: 10, y: 10)
        var size = CGSize(width: 200, height: 240)
        var v = UIView(frame: CGRect(origin: pos, size: size))
        v.backgroundColor = .black
        tgt.addSubview(v)
    }
    
    func paletteConstraints() -> Array<NSLayoutConstraint> {
        var constraints : Array<NSLayoutConstraint> = []
        constraints.append((redRect?.leadingAnchor.constraint( equalTo: view.leadingAnchor, constant: 100))!)
        paletteLeading = constraints.last
        constraints.append((redRect?.topAnchor.constraint( equalTo: view.topAnchor, constant: 100))!)
        paletteTop = constraints.last
        constraints.append((redRect?.widthAnchor.constraint(equalToConstant: 250))! )
        constraints.append((redRect?.heightAnchor.constraint(equalToConstant: 350))! )
        return constraints
    }
    
    func paletteConstraints(_ tgtView : PaletteView ) -> Array<NSLayoutConstraint> {
        var constraints : Array<NSLayoutConstraint> = []
        constraints.append((tgtView.leadingAnchor.constraint( equalTo: redRect!.leadingAnchor)))
        constraints.append((tgtView.topAnchor.constraint( equalTo: redRect!.topAnchor)))
        return constraints
    }
    
    @objc func palettePan(_ sender: UIPanGestureRecognizer) {
        let translation = sender.translation(in: view)
        switch sender.state {
        case .began:
            print("start \(redRect!.frame)")
            paletteLeading?.constant = redRect!.frame.origin.x
            paletteTop?.constant = redRect!.frame.origin.y
        case .changed:
            redRect!.transform = CGAffineTransform(translationX: translation.x, y: translation.y)
        case .ended:
            print("done \(redRect!.frame)")
        default:
            _ = true
        }
    }
}

class PaletteView : UIView {
    var lastPos: CGPoint = CGPoint(x: 20, y: 20)
    
    convenience init() {
        self.init(frame: CGRect(x: 10, y: 10, width: 200, height: 200))
        translatesAutoresizingMaskIntoConstraints = false
    }
}

它可以正常工作,除了在开始新的锅时,它从最后一个锅的末端从其位置跳下来,然后瞬间跳回并可以完成锅。这种跳跃的方向与最后一个平底锅相同,因此第二个锅不会跳跃,随后的盘子朝着最后一个锅走的方向跳跃,大致相同。

这使我认为这与发件人状态相关,但我不知道什么。如果最后一个锅的数量很小,或者锅开始缓慢,则没有闪光灯,但是我无法理解它来自哪里。

情节板中没有限制的视图,但确实可以定义并连接到情节提要中的插座。

This is the code used to control a view with a pan-capable View.

import UIKit

class ViewController: UIViewController {

    @IBOutlet weak var redRect: PaletteView!
    @IBOutlet var paletteTop : NSLayoutConstraint?
    @IBOutlet var paletteLeading : NSLayoutConstraint?
    
    override func viewDidLoad() {
        super.viewDidLoad()
        addRedViewUI(tgt: redRect!)
        redRect.addGestureRecognizer(UIPanGestureRecognizer(target: self, action: #selector(palettePan(_:))))
        redRect?.translatesAutoresizingMaskIntoConstraints = false
        NSLayoutConstraint.activate(paletteConstraints())
    }
    
    func addRedViewUI(tgt : PaletteView) {
        var pos = CGPoint(x: 10, y: 10)
        var size = CGSize(width: 200, height: 240)
        var v = UIView(frame: CGRect(origin: pos, size: size))
        v.backgroundColor = .black
        tgt.addSubview(v)
    }
    
    func paletteConstraints() -> Array<NSLayoutConstraint> {
        var constraints : Array<NSLayoutConstraint> = []
        constraints.append((redRect?.leadingAnchor.constraint( equalTo: view.leadingAnchor, constant: 100))!)
        paletteLeading = constraints.last
        constraints.append((redRect?.topAnchor.constraint( equalTo: view.topAnchor, constant: 100))!)
        paletteTop = constraints.last
        constraints.append((redRect?.widthAnchor.constraint(equalToConstant: 250))! )
        constraints.append((redRect?.heightAnchor.constraint(equalToConstant: 350))! )
        return constraints
    }
    
    func paletteConstraints(_ tgtView : PaletteView ) -> Array<NSLayoutConstraint> {
        var constraints : Array<NSLayoutConstraint> = []
        constraints.append((tgtView.leadingAnchor.constraint( equalTo: redRect!.leadingAnchor)))
        constraints.append((tgtView.topAnchor.constraint( equalTo: redRect!.topAnchor)))
        return constraints
    }
    
    @objc func palettePan(_ sender: UIPanGestureRecognizer) {
        let translation = sender.translation(in: view)
        switch sender.state {
        case .began:
            print("start \(redRect!.frame)")
            paletteLeading?.constant = redRect!.frame.origin.x
            paletteTop?.constant = redRect!.frame.origin.y
        case .changed:
            redRect!.transform = CGAffineTransform(translationX: translation.x, y: translation.y)
        case .ended:
            print("done \(redRect!.frame)")
        default:
            _ = true
        }
    }
}

class PaletteView : UIView {
    var lastPos: CGPoint = CGPoint(x: 20, y: 20)
    
    convenience init() {
        self.init(frame: CGRect(x: 10, y: 10, width: 200, height: 200))
        translatesAutoresizingMaskIntoConstraints = false
    }
}

It works fine, except that when beginning a new pan, it jumps from its position from the end of the last pan, before instantaneously jumping back and the pan can be done. This jump is in the same direction as the last pan, so the second pan the view won't jump, and subsequent pans it jumps in the direction that the last pan went, in roughly the same amount.

This makes me think that it's something associated with the sender state, but I can't figure out what. If the amount of the last pan is small, or the pan is begun slowly, there's no flash, but I haven't been able to understand where that comes from.

The view being panned has no constraints in the storyBoard, but it does get defined and connected to its outlet in the storyboard.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

殤城〤 2025-02-11 16:37:40

解决方案是更改函数,以便在更改约束之后启动和更改执行CGAFFINETRANSFORM:

@objc func palettePan(_ sender: UIPanGestureRecognizer) {
        let translation = sender.translation(in: view)
        switch sender.state {
        case .began:
            print("start \(redRect!.frame)")
            paletteLeading?.constant = redRect!.frame.origin.x
            paletteTop?.constant = redRect!.frame.origin.y
            redRect!.transform = CGAffineTransform(translationX: translation.x, y: translation.y)
        case .changed:
            redRect!.transform = CGAffineTransform(translationX: translation.x, y: translation.y)
        case .ended:
            print("done \(redRect!.frame)")
        default:
            _ = true
        }
    }

The solution is to change the function so both start and changed perform the CGAffineTransform, after the constraints are updated in the case of changed:

@objc func palettePan(_ sender: UIPanGestureRecognizer) {
        let translation = sender.translation(in: view)
        switch sender.state {
        case .began:
            print("start \(redRect!.frame)")
            paletteLeading?.constant = redRect!.frame.origin.x
            paletteTop?.constant = redRect!.frame.origin.y
            redRect!.transform = CGAffineTransform(translationX: translation.x, y: translation.y)
        case .changed:
            redRect!.transform = CGAffineTransform(translationX: translation.x, y: translation.y)
        case .ended:
            print("done \(redRect!.frame)")
        default:
            _ = true
        }
    }
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文