Анимация ограничений с помощью NSView со слоем - PullRequest
2 голосов
/ 24 мая 2019

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

Критически, общая ширина содержащего представления изменяется с окном.Таким образом, анимация на основе констант не возможна (или, как мне кажется, но я рада, что оказалась неправа).

|- viewA -|- viewB -|

Моя первая попытка была использовать NSStackView и анимировать свойство isHiddenорганизованное подпредставление.Несмотря на то, что казалось, что это может сработать, я не смог осуществить что-то похожее на то, что хотел.

Моя вторая попытка состояла в том, чтобы применить два ограничения: одно, чтобы заставить viewB иметь нулевую ширину, иво-вторых, чтобы ширина была одинаковой.При анимации я меняю приоритеты этих ограничений с defaultHigh <-> defaultLow.

В обоих случаях это приводит к правильной компоновке, но анимация не работает.

С wantsLayer = trueна содержащем представлении анимация вообще не происходит.Взгляды просто переходят в свои конечные состояния.Без wantsLayer представления оживляют.Однако при свертывании viewA делает хороший слайд, но viewB мгновенно исчезает.В качестве эксперимента я изменил нулевую ширину на фиксированную 10.0, и с этим анимация работает в обоих направлениях.Однако я хочу, чтобы представление было полностью скрытым.

Итак, несколько вопросов:

Можно ли анимировать макеты, подобные этой, с представлениями со слоями?

Существуют ли другиевозможные методы для достижения того же эффекта?

Есть идеи, как этого добиться с помощью NSStackView?

class LayoutAnimationViewController: NSViewController {
    let containerView: NSView
    let view1: ColorView
    let view2: ColorView
    let widthEqualContraint: NSLayoutConstraint
    let widthZeroConstraint: NSLayoutConstraint

    init() {
        self.containerView = NSView()
        self.view1 = ColorView(color: NSColor.red)
        self.view2 = ColorView(color: NSColor.blue)

        self.widthEqualContraint = view2.widthAnchor.constraint(equalTo: view1.widthAnchor)
        widthEqualContraint.priority = .defaultLow

        self.widthZeroConstraint = view2.widthAnchor.constraint(equalToConstant: 0.0)
        widthZeroConstraint.priority = .defaultHigh

        super.init(nibName: nil, bundle: nil)
    }

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

    override func loadView() {
        self.view = containerView
//        view.wantsLayer = true

        view.addSubview(view1)
        view.addSubview(view2)
        view.subviewsUseAutoLayout = true

        NSLayoutConstraint.activate([
            view1.topAnchor.constraint(equalTo: view.topAnchor),
            view1.bottomAnchor.constraint(equalTo: view.bottomAnchor),
            view1.leadingAnchor.constraint(equalTo: view.leadingAnchor),
//            view1.trailingAnchor.constraint(equalTo: view2.leadingAnchor),

            view2.topAnchor.constraint(equalTo: view.topAnchor),
            view2.bottomAnchor.constraint(equalTo: view.bottomAnchor),
            view2.leadingAnchor.constraint(equalTo: view1.trailingAnchor),
            view2.trailingAnchor.constraint(equalTo: view.trailingAnchor),

            widthEqualContraint,
            widthZeroConstraint,
        ])
    }

    func runAnimation() {
        view.layoutSubtreeIfNeeded()

        self.widthEqualContraint.toggleDefaultPriority()
        self.widthZeroConstraint.toggleDefaultPriority()
//        self.leadingConstraint.toggleDefaultPriority()

        NSAnimationContext.runAnimationGroup({ (context) in
            context.allowsImplicitAnimation = true
            context.duration = 3.0

            self.view.layoutSubtreeIfNeeded()
        }) {
            Swift.print("animation complete")
        }
    }
}

extension LayoutAnimationViewController {
    @IBAction func runTest1(_ sender: Any?) {
        self.runAnimation()
    }
}

Кроме того, некоторые потенциально важные, но пока бесполезные связанные вопросы:

Анимация изменений автоматического макета одновременно с изменением размера содержимого NSPopover

Анимация ограничений автоматического макета с помощью NSView.layoutSubtreeIfNeeded () не работает на macOS High Sierra

Скрыть элемент NSStackView с анимацией

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...