排列的子视图的堆叠视图折叠



我必须使用stackview作为父视图。我正在尝试用2行来设置stackview的动画,以获得折叠和膨胀最下面一行的效果。你可以这么说,当你把这个代码应用到带有子视图的普通自动布局视图时,我试图做的事情和你得到的一样:

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()})
    }
}

简洁利落。当你说点击这个视图时,它会与所有的子视图一起展开或折叠。随着动画的进行,子视图将被剪裁(而不是调整大小/重新缩放),最后您只能看到原始视图的一半。

这看起来很简单,但我无法用stackview完成它。当我将第二行添加到stackview,然后设置layoutIfNeedd()的动画时,如在几个教程中所示,那么:-当底部一排的充气从左侧到达其位置时,-当折叠最下面的一行时,它就消失了(没有动画)-只有背景视图的动画设置正确(参见代码)

当我使用高度约束并且不在底部行的layoutIfNeedd()上设置动画时,则:-当充气时,底部的一行会随着动画的进行而重新缩放到全高-折叠时-当动画进入时,底部一行重新缩放为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()
    })
}

这是最后两个方法的变体,它们使用约束而不是layoutIfNeedd()动画。还有正在修改的约束:

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()
    })
}

那是很久以前的事了,但我认为在布局超视图之前添加self.layoutIfNeedd()有帮助

   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中时,这尤其有用。如果你只在arrangedSubviewsUIStackView上触发layoutIfNeeded,你会在动画中出现奇怪的小故障。

另一个解决方案是过于简单地在UIViewController视图上触发layoutIfNeeded

希望这个答案能有所帮助。

最新更新