Де активировать ограничения между двумя объектами, связывающими их вместе

Мой быстрый код, как вы можете видеть на гифке ниже. Позволяет пользователю выбрать одно из представлений изображения, а затем использовать ползунок для увеличения или уменьшения размера этого представления изображения. Проблема в том, что когда вид изображения перемещается, другой вид изображения следует за ним, чего не должно происходить. Таким образом, ограничения должны быть установлены, когда код запускается в первый раз, но после выбора одного из изображений. Ограничения, связывающие их вместе, должны стать деактивированными. Строка, вызывающая это,

** greenMove.leadingAnchor.constraint (equalTo: view.leadingAnchor, константа: 0), **

введите здесь описание изображения

import UIKit

class ViewController: UIViewController {



    var image1Width: NSLayoutConstraint!
    var image1Height: NSLayoutConstraint!
    var image1Width2: NSLayoutConstraint!
    var image1Height2: NSLayoutConstraint!
    var greenMove = UIImageView()
    var slider = UISlider()
    var blueMove = UIImageView()
    var existingTransition : CGAffineTransform?
    var clock = Int()
    var currentView: UIView?
    var g2 = UIPanGestureRecognizer()
    var g3 = UIPanGestureRecognizer()

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.
        greenMove.isUserInteractionEnabled = true
        blueMove.isUserInteractionEnabled = true

        g2 = UIPanGestureRecognizer(target: self, action: #selector(ViewController.g1Method))
        greenMove.addGestureRecognizer(g2)
        g3 = UIPanGestureRecognizer(target: self, action: #selector(ViewController.g2Method))
        blueMove.addGestureRecognizer(g3)

        greenMove.backgroundColor = .systemGreen

        blueMove.backgroundColor = .blue


        [greenMove,slider,blueMove].forEach {

            view.addSubview($0)
            $0.translatesAutoresizingMaskIntoConstraints = false

        }


        //image11
        image1Width =  greenMove.widthAnchor.constraint(equalTo:  view.widthAnchor ,multiplier:  0.2)
        image1Height =  greenMove.heightAnchor.constraint(equalTo:  view.heightAnchor ,multiplier:  0.20)

        //image12
        image1Width2 =  blueMove.widthAnchor.constraint(equalTo:  view.widthAnchor ,multiplier:  0.2)
        image1Height2 =  blueMove.heightAnchor.constraint(equalTo:  view.heightAnchor ,multiplier:  0.20)



        NSLayoutConstraint.activate([

            greenMove.topAnchor.constraint(equalTo: view.topAnchor, constant : 0),
            image1Width,
            image1Height,
            greenMove.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant :0),


            blueMove.topAnchor.constraint(equalTo: view.topAnchor, constant : 0),
            image1Width2,
            image1Height2,
            blueMove.leadingAnchor.constraint(equalTo: greenMove.trailingAnchor, constant :0)

        ])








        slider.addTarget(self, action: #selector(hhh), for: .allEvents)

    }

    override func viewDidLayoutSubviews() {
        NSLayoutConstraint.activate ([




            slider.topAnchor.constraint(equalTo: view.topAnchor, constant : greenMove.bounds.height),
            slider.heightAnchor.constraint(equalTo: view.heightAnchor, multiplier: 0.20, constant: 0),
            slider.widthAnchor.constraint(equalTo: view.widthAnchor, multiplier: 0.20, constant: 0),
            slider.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant : 0),


        ])
    }
    @objc func handleTapGestured(_ gesture: UIPanGestureRecognizer) {
        currentView = gesture.view
    }

    @objc func g1Method(_ sender: UIPanGestureRecognizer){
        clock = 1
        let subview = greenMove
        guard let child = sender.view else{return}
        let transitionPoint = sender.translation(in: self.view)
        let newTransition = CGAffineTransform(translationX: transitionPoint.x, y: transitionPoint.y)
        switch sender.state {

        case .ended,.cancelled:// on End
            if let existing = existingTransition{
                self.existingTransition = newTransition.concatenating(existing)
            }else{
                self.existingTransition = newTransition
            }
        default://on change and other states
            if let existing = existingTransition{
                child.transform = newTransition
                    .concatenating(existing)
            }else{
                child.transform = newTransition
            }
        }
        self.view.layoutIfNeeded()


        let tapGesture = UITapGestureRecognizer(target: self, action: #selector(handleTapGestured(_:)))
        subview.addGestureRecognizer(tapGesture)


    }
    @objc func g2Method(_ sender: UIPanGestureRecognizer){
        clock = 2
        let subview = blueMove
        guard let child = sender.view else{return}
        let transitionPoint = sender.translation(in: self.view)
        let newTransition = CGAffineTransform(translationX: transitionPoint.x, y: transitionPoint.y)
        switch sender.state {

        case .ended,.cancelled:// on End
            if let existing = existingTransition{
                self.existingTransition = newTransition.concatenating(existing)
            }else{
                self.existingTransition = newTransition
            }
        default://on change and other states
            if let existing = existingTransition{
                child.transform = newTransition
                    .concatenating(existing)
            }else{
                child.transform = newTransition
            }
        }
        self.view.layoutIfNeeded()


        let tapGesture = UITapGestureRecognizer(target: self, action: #selector(handleTapGestured(_:)))
        subview.addGestureRecognizer(tapGesture)


    }
    @objc func hhh() {

        if clock ==  1 {
            image1Width.constant = CGFloat(slider.value) * view.frame.size.width * 0.25
            image1Height.constant = CGFloat(slider.value) * view.frame.size.height * 0.25
        }
        if clock  == 2 {

            image1Width2.constant = CGFloat(slider.value) * view.frame.size.width * 0.25
            image1Height2.constant = CGFloat(slider.value) * view.frame.size.height * 0.25
        }




    }

}



Ответы (2)


Проблема, с которой вы сталкиваетесь, заключается в том, что вы используете одно преобразование для обоих представлений и объединяете новую информацию о преобразовании, которая применяется к другому представлению, когда вы пытаетесь его переместить.

Внесите эти изменения в опубликованный код...

На уровне класса создайте отдельные трансформирующие «трекеры»:

// don't use this
//var existingTransition : CGAffineTransform?

// separate transforms for each "move view"
var blueTransition: CGAffineTransform?
var greenTransition: CGAffineTransform?

Затем в g1Method и g2Method используйте связанное преобразование:

@objc func g1Method(_ sender: UIPanGestureRecognizer){
    clock = 1
    let subview = greenMove
    guard let child = sender.view else{return}
    let transitionPoint = sender.translation(in: self.view)
    let newTransition = CGAffineTransform(translationX: transitionPoint.x, y: transitionPoint.y)

    // greenMove view must track its own CGAffineTransform

    switch sender.state {

    case .ended,.cancelled:// on End
        if let existing = greenTransition {
            greenTransition = newTransition.concatenating(existing)
        } else {
            greenTransition = newTransition
        }
        //if let existing = existingTransition{
        //  self.existingTransition = newTransition.concatenating(existing)
        //}else{
        //  self.existingTransition = newTransition
        //}
    default://on change and other states
        if let existing = greenTransition {
            child.transform = newTransition
                .concatenating(existing)
        } else {
            child.transform = newTransition
        }
        //if let existing = existingTransition{
        //  child.transform = newTransition
        //      .concatenating(existing)
        //}else{
        //  child.transform = newTransition
        //}
    }
    self.view.layoutIfNeeded()

    // move this to viewDidLoad(), otherwise you are adding ANOTHER recognizer each time this method is called
    //let tapGesture = UITapGestureRecognizer(target: self, action: #selector(handleTapGestured(_:)))
    //subview.addGestureRecognizer(tapGesture)


}
@objc func g2Method(_ sender: UIPanGestureRecognizer){
    clock = 2
    let subview = blueMove
    guard let child = sender.view else{return}
    let transitionPoint = sender.translation(in: self.view)
    let newTransition = CGAffineTransform(translationX: transitionPoint.x, y: transitionPoint.y)

    // blueMove view must track its own CGAffineTransform

    switch sender.state {

    case .ended,.cancelled:// on End
        if let existing = blueTransition {
            blueTransition = newTransition.concatenating(existing)
        } else {
            blueTransition = newTransition
        }
        //if let existing = existingTransition{
        //  self.existingTransition = newTransition.concatenating(existing)
        //}else{
        //  self.existingTransition = newTransition
        //}
    default://on change and other states
        if let existing = blueTransition {
            child.transform = newTransition
                .concatenating(existing)
        } else {
            child.transform = newTransition
        }
        //if let existing = existingTransition{
        //  child.transform = newTransition
        //      .concatenating(existing)
        //}else{
        //  child.transform = newTransition
        //}
    }
    self.view.layoutIfNeeded()

    // move this to viewDidLoad(), otherwise you are adding ANOTHER recognizer each time this method is called
    //let tapGesture = UITapGestureRecognizer(target: self, action: #selector(handleTapGestured(_:)))
    //subview.addGestureRecognizer(tapGesture)


}
person DonMag    schedule 11.05.2020

Лучший способ — создать ведущее ограничение для синего изображения между начальным изображением безопасной области и начальным изображением, а не между двумя изображениями, потому что, когда вы отключите ограничение между двумя изображениями, у вас будет ошибка, потому что представление не знает, куда поместить начальное изображение. изображение

person Andrea    schedule 09.05.2020