Ввод текста в текстовое поле приводит к тому, что объект uipangesture возвращается в исходное положение - PullRequest
0 голосов
/ 18 февраля 2020

В моем быстром коде, приведенном ниже, есть изображение, подключенное к пангестеру. Когда что-то вводится в текстовое поле, когда после просмотра изображения перемещается. Представление изображения возвращается в исходное положение. GIF представляет то, что происходит. Я просто не хочу, чтобы эффект pangesutre был аннулирован после ввода текста в текстовое поле.

enter image description here ССЫЛКА НА GITHUB https://github.com/redrock34/sse

import UIKit

class ViewController: UIViewController {

    var pic = UIImageView()
    let fight = (0..<10).map { _ in UIImageView() }
    var textEnter = UITextField()
    var g2 = UIPanGestureRecognizer()

    var slider = UISlider()

    override func viewDidLoad() {
        super.viewDidLoad()

        fight[0].image  = UIImage(named: "a.png")

        fight.forEach{
            $0.isUserInteractionEnabled = true
        }
        [slider,textEnter].forEach{
            $0.translatesAutoresizingMaskIntoConstraints = false
            view.addSubview($0)

            $0.backgroundColor = .blue
        }

        slider.backgroundColor = .clear

        g2 = UIPanGestureRecognizer(target: self, action: #selector(ViewController.g1Method))
        fight[0].addGestureRecognizer(g2)

        pic.backgroundColor = .clear
        pic.backgroundColor = .systemGreen

        fight.forEach{
            $0.backgroundColor = .clear
            view.addSubview($0)
            $0.translatesAutoresizingMaskIntoConstraints = false
        }            

        [pic].forEach{

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

        // Do any additional setup after loading the view.
        NSLayoutConstraint.activate ([

            pic.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant :0),
            pic.topAnchor.constraint(equalTo: fight[0].bottomAnchor, constant : 0),

            pic.heightAnchor.constraint(equalTo: view.heightAnchor, multiplier: 0.62, constant: 0),
            pic.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant : 0),

            textEnter.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant :0),
            textEnter.topAnchor.constraint(equalTo: view.topAnchor, constant : 0),
            textEnter.heightAnchor.constraint(equalTo: view.heightAnchor, multiplier: 0.1, constant: 0),
            textEnter.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant : 0),

            fight[0].trailingAnchor.constraint(equalTo: view.trailingAnchor, constant :0),
            fight[0].topAnchor.constraint(equalTo: textEnter.bottomAnchor, constant : 0),

            fight[0].heightAnchor.constraint(equalTo: view.heightAnchor, multiplier: 0.10, constant: 0),
            fight[0].widthAnchor.constraint(equalTo: view.widthAnchor, multiplier: 0.10, constant: 0),
            fight[0].leadingAnchor.constraint(equalTo: view.leadingAnchor, constant : 0),

            slider.topAnchor.constraint(equalTo: pic.bottomAnchor, constant : 0),

            slider.heightAnchor.constraint(equalTo: view.heightAnchor, multiplier: 0.08, constant: 0),
            slider.widthAnchor.constraint(equalTo: view.widthAnchor, multiplier: 1, constant: 0),
            slider.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant : 0),

        ])
        textEnter.textAlignment = .center

        self.view.sendSubviewToBack(pic)
    }

    @objc func g1Method(_ sender: UIPanGestureRecognizer){

        let tranistioon = sender.translation(in: self.view)
        sender.view!.center = CGPoint(x: sender.view!.center.x + tranistioon.x, y: sender.view!.center.y + tranistioon.y)
        sender.setTranslation(CGPoint.zero,in: self.view)    }
}

Ответы [ 3 ]

2 голосов
/ 05 марта 2020

Здравствуйте, попробуйте создать класс UIImageVIew и напишите следующий код:

import UIKit

class draggableImage:UIImageView {


    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        self.layer.borderWidth = 1
        self.layer.borderColor = UIColor.red.cgColor
        self.isUserInteractionEnabled = true
    }



    override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
        let touch = touches.first;
        let location = touch?.location(in: self.superview);
        if(location != nil)
        {
        self.frame.origin = CGPoint(x: location!.x-self.frame.size.width/2, y: location!.y-self.frame.size.height/2);
        }
    }

    override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {

    }

}

Не забудьте назначить класс draggableImage для представления изображения из меню атрибутов! Надеюсь, что это работает для вас ~ BY DEV

0 голосов
/ 05 марта 2020

Нельзя смешивать явные настройки фрейма с ограничениями автоматического макета для одного и того же объекта.

Например, если вы:

  • добавляете метку в основной вид
  • set label.translatesAutoresizingMaskIntoConstraints = false
  • установить ограничения для метки

, затем с помощью кода ...

  • изменить свойство .center метка

вы увидите перемещение метки, но когда произойдет следующее обновление пользовательского интерфейса (вы редактируете текстовое поле, нажимаете кнопку, поворачиваете устройство и т. д. c), автоматическое расположение будет сбросить рамку метки на основе ее ограничений.

Итак, в вашем обработчике жестов панорамирования вы можете либо обновить значения .constant для объекта fight[0] (вместо изменения .center), или ...

Вы можете оставить label.translatesAutoresizingMaskIntoConstraints = true для своих fight объектов и явно установить их рамки и центры.

Примечание: в любом случае вы делаете не хотите ограничить любые другие элементы относительно fight объектов, или они будут двигаться при перемещении fight[0].

H Это модификация вашего ViewController класса (из вашего почтового индекса GitHub), реализующая метод not с использованием ограничений автоматического размещения на ваших боевых объектах.

class ViewController: UIViewController {

    var pic = UIImageView()
    let fight = (0..<10).map { _ in UIImageView() }
    var textEnter = UITextField()
    var g2 = UIPanGestureRecognizer()

    var slider = UISlider()

    override func viewDidLoad() {
        super.viewDidLoad()

        fight[0].image  = UIImage(named: "a.png")

        fight.forEach{
            $0.isUserInteractionEnabled = true
        }
        [slider,textEnter].forEach{
            $0.translatesAutoresizingMaskIntoConstraints = false
            view.addSubview($0)
            $0.backgroundColor = .blue
        }

        slider.backgroundColor = .clear

        g2 = UIPanGestureRecognizer(target: self, action: #selector(ViewController.g1Method))
        fight[0].addGestureRecognizer(g2)

        pic.backgroundColor = .systemGreen

        fight.forEach{
            $0.backgroundColor = .clear
            view.addSubview($0)
            // do NOT use auto-layout for fight views
            //$0.translatesAutoresizingMaskIntoConstraints = false
        }

        [pic].forEach{
            view.addSubview($0)
            $0.translatesAutoresizingMaskIntoConstraints = false
        }

        // need a non-rendering "spacer" to vertically separate textEnter from Pic
        let spacer = UILayoutGuide()
        view.addLayoutGuide(spacer)

        // NOTE: do NOT constrain any elements relative to fight views

        NSLayoutConstraint.activate ([

            // constrain textEnter top / leading / trailing to view
            textEnter.topAnchor.constraint(equalTo: view.topAnchor, constant : 0),
            textEnter.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant : 0),
            textEnter.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant :0),
            // constrain textEnter height to 0.1 * view height
            textEnter.heightAnchor.constraint(equalTo: view.heightAnchor, multiplier: 0.1, constant: 0),

            // constrain spacer top to bottom of textEnter
            spacer.topAnchor.constraint(equalTo: textEnter.bottomAnchor, constant: 0.0),
            // constrain spacer leading to view leading
            spacer.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 0.0),
            // constrain spacer height to 0.1 * view height
            spacer.heightAnchor.constraint(equalTo: view.heightAnchor, multiplier: 0.10),
            // spacer width doesn't matter
            spacer.widthAnchor.constraint(equalToConstant: 1.0),

            // constrain pic Top to spacer bottom
            pic.topAnchor.constraint(equalTo: spacer.bottomAnchor, constant: 0.0),
            // constrain pic leading / trailing to view
            pic.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant : 0),
            pic.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant :0),

            // constrain pic height as you had it
            pic.heightAnchor.constraint(equalTo: view.heightAnchor, multiplier: 0.62, constant: 0),

            // slider constraints
            slider.topAnchor.constraint(equalTo: pic.bottomAnchor, constant : 0),
            slider.heightAnchor.constraint(equalTo: view.heightAnchor, multiplier: 0.08, constant: 0),
            slider.widthAnchor.constraint(equalTo: view.widthAnchor, multiplier: 1, constant: 0),
            slider.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant : 0),

        ])

        textEnter.textAlignment = .center

        self.view.sendSubviewToBack(pic)

    }

    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)
        // set fight[0] frame *after* textEnter has been laid-out
        fight[0].frame.size = CGSize(width: view.frame.width * 0.10, height: view.frame.height * 0.10)
        let x = view.frame.origin.x
        let y = textEnter.frame.origin.y + textEnter.frame.size.height
        fight[0].frame.origin = CGPoint(x: x, y: y)
    }

    @objc func g1Method(_ sender: UIPanGestureRecognizer){

        let tranistioon = sender.translation(in: self.view)
        sender.view!.center = CGPoint(x: sender.view!.center.x + tranistioon.x, y: sender.view!.center.y + tranistioon.y)
        sender.setTranslation(CGPoint.zero,in: self.view)

    }

}
0 голосов
/ 05 марта 2020

Используйте этот метод вместо

  var existingTransition : CGAffineTransform?
    @objc func g1Method(_ sender: UIPanGestureRecognizer){
        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()
    }

Извините, если мой код грязный. Но я проверил некоторые Scena ios, он работает нормально.

Happy Codding

...