Анимация стека - падение упорядоченных подпредставлений
Я должен использовать StackView в качестве родительского представления. Я пытаюсь анимировать просмотр стека с 2 рядами, чтобы получить эффект свертывания и раздувания нижнего ряда. Вы можете сказать, что то, что я пытаюсь сделать, это то же самое, что вы получаете, когда применяете этот код к обычному автолюбированному представлению с подпредставлениями:
func showView()
{
if(!expand)
{ UIView.animateWithDuration(0.5, animations:{
self.expandableViewHeight.constant = 50
// Update layout of all subviews
self.parentViewController!.view.layoutIfNeeded()})
} else {
UIView.animateWithDuration(0.5, animations:{
self.expandableViewHeight.constant = 100
// Update layout of all subviews
self.parentViewController!.view.layoutIfNeeded()})
}
}
Просто и аккуратно. Скажем, если вы щелкнете по этому представлению, оно развернется или свернется со всеми его подпредставлениями. По мере анимации подпредставления обрезаются (не изменяются или не изменяются в размере), и, наконец, вы можете видеть только половину исходного представления.
Это выглядит как простая вещь, но я не могу сделать это с помощью стека. Когда я добавляю вторую строку к просмотру стека и затем анимирую layoutIfNeeded(), как в нескольких уроках, то: - при накачивании нижняя строка переходит слева на свою позицию, - когда сворачивающаяся нижняя строка просто исчезает (без анимации) - только фоновый вид правильно анимирован (см. код)
Когда я использую ограничения по высоте и не анимирую layoutIfNeeded () в нижнем ряду, тогда: - при накачивании нижний ряд масштабируется до полной высоты при анимации - при свертывании - нижний ряд масштабируется до 0 как анимация идет
Не могу заставить его обрезать нижний ряд! Любые советы приветствуются!:)
Это мой код стека:
override func viewDidLoad(){
super.viewDidLoad()
background = UIView(frame:CGRectMake(0, 0, frame.width,frame.height))
background.backgroundColor = UIColor.whiteColor()
background.layer.cornerRadius = 5
background.layer.masksToBounds = true
self.addSubview(background)
vStack = UIStackView()
vStack.axis = .Vertical
vStack.alignment = .Fill
vStack.distribution = .Fill
vStack.spacing = 0
self.addArrangedSubview(vStack)
hStack = UIStackView()
hStack.axis = .Horizontal
hStack.alignment = .Center
hStack.distribution = .EqualSpacing
hStack.spacing = 10
hStack2 = UIStackView()
hStack2.axis = .Horizontal
hStack2.alignment = UIStackViewAlignment.Center
hStack2.distribution = UIStackViewDistribution.EqualCentering
hStack2.spacing = 10
lquestionStack = UIStackView()
questionStack.axis = .Horizontal
questionStack.alignment = .Center
questionStack.distribution = .EqualSpacing
questionStack.spacing = QUESTION_PADDING
let labelQuestionNumber = UIButton()
labelQuestionNumber.userInteractionEnabled = false
let numberImage = UIImage(named: "backgroundImage")
labelQuestionNumber.setBackgroundImage(numberImage, forState: .Normal)
questionStack.addArrangedSubview(labelQuestionNumber)
hStack.addArrangedSubview(questionStack)
vStack.addArrangedSubview(hStack)
hStack2.addArrangedSubview(questionStack)
vStack.addArrangedSubview(hStack2)
}
public func collapseInflateAction() {
if checkWidget.collapsed {
inflateWidget()
} else {
collapseWidget()
}
checkWidget.collapsed = !checkWidget.collapsed
}
private func collapseWidget(){
vStack.removeArrangedSubview(self.hStack2)
self.hStack2.removeFromSuperview()
UIView.animateWithDuration(0.5, animations: { () -> Void in
self.background.frame.size.height = (self.background.frame.size.height)/2
self.layoutIfNeeded()
self.superview?.layoutIfNeeded()
})
}
private func inflateWidget(){
self.vStack.addArrangedSubview(self.hStack2)
UIView.animateWithDuration(0.5, animations: { () -> Void in
self.background.frame.size.height = self.background.frame.size.height*2
self.layoutIfNeeded()
self.superview?.layoutIfNeeded()
})
}
И это вариант 2 последних методов, которые используют ограничения вместо layoutIfNeeded () анимации. А также изменяемое ограничение:
override func viewDidLoad(){
super.viewDidLoad()
(...)
heightConstraint = NSLayoutConstraint(item: hStack2, attribute: NSLayoutAttribute.Height, relatedBy: NSLayoutRelation.Equal, toItem: nil, attribute: NSLayoutAttribute.NotAnAttribute, multiplier: 1, constant: 0)
self.addConstraint(heightConstraint)
}
private func collapseWidget(){
UIView.animateWithDuration(0.5, animations: { () -> Void in
self.background.frame.size.height = 44
self.heightConstraint.constant = 0
self.superview?.layoutIfNeeded()
})
}
private func inflateWidget(){
UIView.animateWithDuration(0.5, animations: { () -> Void in
self.background.frame.size.height = 88
self.heightConstraint.constant = 44
self.superview?.layoutIfNeeded()
})
}
1 ответ
Это было давно, но я думаю, что это помогло добавить self.layoutIfNeeded() перед компоновкой superview
fileprivate func collapseWidget(){
UIView.animate(withDuration: 0.25, animations: { () -> Void in
self.background.frame.size.height = self.heightCollapsed
self.heightConstraint.constant = self.heightCollapsed
self.layoutIfNeeded()
self.superview?.layoutIfNeeded()
})
}
fileprivate func inflateWidget(){
self.separatorView.isHidden = false
UIView.animate(withDuration: 0.25, animations: { () -> Void in
self.background.frame.size.height = self.heightInflated
self.heightConstraint.constant = self.heightInflated
self.layoutIfNeeded()
self.superview?.layoutIfNeeded()
})
}
В этом случае что-то, что может помочь людям заставить их анимацию работать плавно, - это запуск layoutIfNeeded()
на самом высоком уровне иерархии.
Это особенно полезно, когда вы UIStackView
встроен в UIScrollView
. Если вы только запускаетеlayoutIfNeeded
на ваше arrangedSubviews
или на UIStackView
вы получите странные сбои в вашей анимации.
Другое решение - слишком простой триггер layoutIfNeeded
на ваше UIViewController
Посмотреть.
Надеюсь, этот ответ поможет.