首页 > 解决方案 > 仅在其父视图内拖动 UIImageView

问题描述

假设我有:

现在换句话说,我只想fox在它里面移动fence

在我的viewDidLoad()

override func viewDidLoad() {
    super.viewDidLoad()

    view.addSubview(fence)
    fence.addSubview(fox)

}

现在这部分工作正常,我想通过一些修改来移动fox子类:UIImageView

class DraggableImageView: UIImageView {


var dragStartPositionRelativeToCenter : CGPoint?

override init(image: UIImage!) {
    super.init(image: image)

    self.isUserInteractionEnabled = true 

    addGestureRecognizer(UIPanGestureRecognizer(target: self, action: #selector(handlePan(nizer:))))

    layer.shadowColor = UIColor.black.cgColor
    layer.shadowOffset = CGSize(width: 0, height: 3)
    layer.shadowOpacity = 0.5
    layer.shadowRadius = 2
}

required init?(coder aDecoder: NSCoder) {
    fatalError("init(coder:) has not been implemented")
}

@objc func handlePan(nizer: UIPanGestureRecognizer!) {
    if nizer.state == UIGestureRecognizer.State.began {
        let locationInView = nizer.location(in: superview)
        dragStartPositionRelativeToCenter = CGPoint(x: locationInView.x - center.x, y: locationInView.y - center.y)

        layer.shadowOffset = CGSize(width: 0, height: 20)
        layer.shadowOpacity = 0.3
        layer.shadowRadius = 6

        return
    }

    if nizer.state == UIGestureRecognizer.State.ended {
        dragStartPositionRelativeToCenter = nil

        layer.shadowOffset = CGSize(width: 0, height: 3)
        layer.shadowOpacity = 0.5
        layer.shadowRadius = 2

        return
    }

    let locationInView = nizer.location(in: superview)

    UIView.animate(withDuration: 0.1) {
        self.center = CGPoint(x: locationInView.x - self.dragStartPositionRelativeToCenter!.x,
                              y: locationInView.y - self.dragStartPositionRelativeToCenter!.y)
    }
}}

现在我可以将fox对象拖到任何我喜欢的地方,但是;如果我只想移动对象fox内部怎么办fence?,因为它是一个子视图,我认为这是可能的。

标签: iosswift

解决方案


为了将图像视图保持在其父级中,我在更新视图的中心之前添加了一个检查,以确保视图框架将位于父级框架中。仅当更新将视图保持在其父框架内时,中心才会更新。

我还更新了平移处理程序以使用翻译(类似于平移手势文档中的示例),而不是 locationInView。这使得阻力表现更好。

我已经对此进行了测试,我相信它会按照您想要的方式运行。希望这可以帮助:

    @objc func handlePan(nizer: UIPanGestureRecognizer!) {
        if nizer.state == UIGestureRecognizer.State.began {
            dragStartPositionRelativeToCenter = self.center
            layer.shadowOffset = CGSize(width: 0, height: 20)
            layer.shadowOpacity = 0.3
            layer.shadowRadius = 6

            return
        }

        if nizer.state == UIGestureRecognizer.State.ended {
            dragStartPositionRelativeToCenter = nil

            layer.shadowOffset = CGSize(width: 0, height: 3)
            layer.shadowOpacity = 0.5
            layer.shadowRadius = 2

            return
        }

        if let initialCenter = dragStartPositionRelativeToCenter {
            let translation = nizer.translation(in: self.superview)
            let newCenter = CGPoint(x: initialCenter.x + translation.x, y: initialCenter.y + translation.y)
            if frameContainsFrameFromCenter(containingFrame: superview!.frame, containedFrame: self.frame, center: newCenter) {
                UIView.animate(withDuration: 0.1) {
                    self.center = newCenter
                }
            }

        }
    }

    func frameContainsFrameFromCenter(containingFrame: CGRect, containedFrame: CGRect, center: CGPoint) -> Bool {
        let leftMargin = containedFrame.width / 2
        let topMargin = containedFrame.height / 2
        let testFrame = CGRect(
            x: leftMargin,
            y: topMargin,
            width: containingFrame.width - (2*leftMargin),
            height: containingFrame.height - (2*topMargin)
        )
        return testFrame.contains(center)
    }

推荐阅读