Перетаскивание UIImageView только внутри родительского представления - PullRequest
1 голос
/ 07 июня 2019

Допустим, у меня есть:

  • UIImageView с именем fox
  • Родительский ImageView с именем fence
  • Мастер UIView встроенныйв ViewControllers по умолчанию

Теперь, другими словами, я хочу, чтобы 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 объекта ?, так как это подпредставление, я думаю, что это возможно.

1 Ответ

2 голосов
/ 07 июня 2019

Чтобы сохранить представление изображения внутри его родителя, я добавил проверку перед обновлением центра представления, которая гарантирует, что кадр представлений будет находиться в кадре родителей.Центр обновляется только в том случае, если обновление сохранит представление в рамке его родителя.

Я также обновил обработчик панорамирования, чтобы использовать перевод (аналогично примеру в жесте панорамирования документация )в отличие от 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)
    }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...