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