Как использовать PanGestureRecognizer для изменения положения подслоя? - PullRequest
0 голосов
/ 11 декабря 2018

Я хотел бы изменить положение подслоев, щелкая и перетаскивая.Я испытываю трудности и собрал простую демонстрацию, чтобы проиллюстрировать проблемы.См. Код ниже и / или этот исполняемый проект, который включает в себя игровую площадку, на GitHub.

Пользовательский интерфейс демонстрации (см. Изображение ниже) состоит из трех элементов: основной вид (черный), подпредставление (красный) и подуровень подпредставления (серый).Оба вида имеют распознаватель жестов касания, который сообщает на консоль.Кроме того, подпредставление имеет средство распознавания панорамирования, которое позволяет переместить подпредставление и / или его подуровень, а также отправлять отчеты в консоль.

The demo project's UI

Первая проблема - Подуровень отстает от жеста.

  1. На моем устройстве и на игровой площадке: если я коснусь и перетащу красное подпредставление, тогда он будет точно отслеживать палец / курсорЧто ж;серый подслой движется вместе с ним.Если я коснусь и перетащу серый подслой, то он отстает: я должен двигаться медленно или сделать паузу и ждать, пока он наверстает упущенное.
  2. На симуляторе: ни красный подпредставление, ни серый подслой не отслеживают курсор.Они остаются неподвижными до тех пор, пока я не остановлюсь, и в этот момент они быстро переместятся в новое положение.

Вторая проблема - Я не могу схватить серый подслой близко к его краю.

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

Спасибо, что нашли время подумать об этом.Любой совет будет оценен.

import UIKit

public class ViewController: UIViewController {

    override public func loadView() {
        let mainView = UIView(frame: CGRect.zero)
        mainView.backgroundColor = .black
        mainView.layer.name = "Main View's Layer"
        mainView.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(tapGestureRecognized(_:))))
        self.view = mainView
    }

    override public func viewDidLayoutSubviews() {
        let subview = UIView(frame: view.bounds.insetBy(dx: 50.0, dy: 100.0))
        subview.backgroundColor = .red
        subview.layer.name = "Sub View's Layer"
        subview.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(tapGestureRecognized(_:))))
        subview.addGestureRecognizer(UIPanGestureRecognizer(target: self, action: #selector(panGestureRecognized(_:))))

        let sublayer = CALayer()
        sublayer.bounds = subview.layer.bounds.insetBy(dx: 50, dy: 100)
        sublayer.name = "Sub View's Sublayer"
        sublayer.position = CGPoint(x: subview.layer.bounds.midX, y: subview.layer.bounds.midY)
        sublayer.backgroundColor = UIColor.gray.cgColor
        subview.layer.addSublayer(sublayer)

        view.addSubview(subview)
    }

    // **********************************************************************************************************************

    private struct TouchedLayer : CustomStringConvertible {

        var layer: CALayer
        let startingPosition: CGPoint

        init(recognizer: UIGestureRecognizer) {
            let view = recognizer.view!
            let touchLocation = recognizer.location(in: view)
            let hitTestLocation = view.layer.superlayer!.convert(touchLocation, from: view.layer)

            layer = view.layer.hitTest(hitTestLocation)!
            startingPosition = layer.position
        }

        mutating func updateLayerPosition(translation: CGPoint) {
            layer.position = CGPoint(x: startingPosition.x + translation.x, y: startingPosition.y + translation.y)
        }

        var description: String {
            return "\(layer.name ?? "<Unknown>"): position = \(layer.position)"
        }
    }

    @objc func tapGestureRecognized(_ sender: UITapGestureRecognizer) {
        guard sender.state == .ended else { return }

        let tappedLayer = TouchedLayer(recognizer: sender)
        print("\nTapped", tappedLayer)
    }

    private var panningLayer: TouchedLayer!
    @objc func panGestureRecognized(_ sender: UIPanGestureRecognizer) {
        switch sender.state {
        case .began:
            panningLayer = TouchedLayer(recognizer: sender)
            print("\nPanning Begun - \(panningLayer!)")
        case .changed:
            panningLayer.updateLayerPosition(translation: sender.translation(in: sender.view))
            //print("\tPanning - \(panningLayer!)")
        default:
            print("Panning Ended - \(panningLayer!)")
        }
    }
}

1 Ответ

0 голосов
/ 11 декабря 2018

Я хотел бы изменить положение подслоев, щелкнув и перетащив

Я бы предложил, чтобы вы перестали хотеть это делать.Слой не имеет сенсорной способности, в то время как вид имеет;действительно, было мудро сказано, что представление - это слой плюс осязаемость.Если бы вы использовали подпредставления вместо подслоев, стало бы возможным непосредственно прикоснуться к подпредставлению, иметь распознаватель жестов, коснуться и панорамировать обычным способом и так далее.Вы просто излишне усложняете себе жизнь, не получая (насколько мне известно) ощутимой выгоды, используя слои вместо представлений.

...