I need to use stackview as a parent view. I am trying to animate a stackview with two lines to get the effect of folding and inflating the bottom line. You can say that what I'm trying to do is the same thing that you get when you apply this code to regular autostarts using subviews:
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()}) } }
Simple and neat. When you allow speaking, click on this view, it expands or collapses with all its subviews. Mobility is cropped (not resized / scaled) when the animation is on, and finally, you can only see half of the original view.
This seems like a simple thing, but I can't do it with stackview. When I add the second line to the stackview, and then the layoutIfNeeded () animation, as in several tutorials, then: - when the lower row is inflated, it occurs to the left of it, - when minimized, the lower row simply disappears (without animation) - only the background view is animated correctly ( see code)
When I use height restrictions and do not animate it in layoutIfNeeded () on the bottom line, then: - when the bottom row is inflated, it is scaled to full height as the animation moves - when minimized, the bottom line is scaled to 0 when the animation goes
Unable to fix bottom row! Any advice appreciated! :)
This is my stack code:
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() }) }
And this is a variation of the last two methods that use constraints instead of layoutIfNeeded () animations. And also a mutable constraint:
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() }) }