如何以编程方式为ios 9中的UIStackView的对齐属性设置动画

时间:2017-03-02 00:10:14

标签: ios objective-c core-animation ios-autolayout uistackview

我想知道如何设置水平UIStackView的对齐属性的更改动画,从UIStackViewAlignmentCenter到UIStackViewAlignmentTop,反之亦然,我想在视觉上反映这一变化。

编辑:

我有什么:

这是我的观点层次结构:

  • 两个名为b1和b2的按钮; b1有一个名为" changeAlignmentToTop"和b2有一个名为" changeAlignmentToCenter"的动作,它们被激活在相应的按钮中触摸内部。
  • 一个名为Pview的UIView框架(0,100,414,100)。
    • 一个名为S1的水平UIStackView,其alignment属性设置为" center"。此stackView已固定到pView的边框。
      • 一个名为S2的水平UIStackView,其alignment属性设置为" Fill"并且里面有两个标签。

我想做什么:

我想改变S1与#34; Center"的对齐方式。 to" Top"当我触摸按钮b1并且我想要改变它的动画。

我尝试了什么

- (void) changeAlignmentToTop {
  [UIView animationWithduration 0.3 animations : ^{
    S1.alignment = UIStackViewAlignmentTop;
    // here I'd prove several options
    // option - 1
    [S1 setNeedsDisplay];
    [S1 layoutIfNeeded];
    // option - 2
    //[S1 setNeedsLayout];
    //[S1 layoutIfNeeded];
    // option - 3
    //[S1 setNeedsDisplay];
    //[pView layoutIfNeeded];
    // option - 4
    //[pView setNeedsDisplay];
    //[pView layoutIfNeeded];
    // option - 5
    //[pView setNeedsDisplay];
    //[self.view layoutIfNeeded];
  } completion: nil];
}

- (void) changeAlignmentToCenter {
  [UIView animationWithduration 0.3 animations : ^{
    S1.alignment = UIStackViewAlignmentCenter;
    // here I'd prove several options
    // option - 1
    [S1 setNeedsDisplay];
    [S1 layoutIfNeeded];
    // option - 2
    //[S1 setNeedsLayout];
    //[S1 layoutIfNeeded];
    // option - 3
    //[S1 setNeedsDisplay];
    //[pView layoutIfNeeded];
    // option - 4
    //[pView setNeedsDisplay];
    //[pView layoutIfNeeded];
    // option - 5
    //[pView setNeedsDisplay];
    //[self.view layoutIfNeeded];
  } completion: nil];
}

这些选项都不起作用。对象更改但UI不反映它既不动画任何东西。如果我更改轴的对齐(尝试将轴从水平更改为垂直,反之亦然),一切顺利。如果我动画地更改了两个标签中使用的字体的大小,那么问​​题就在于stackView的对齐方式。但根据苹果文档,对齐属性是可动画的,所以我做错了吗?

任何人都可以帮助我吗?

提前致谢

1 个答案:

答案 0 :(得分:0)

所以希望我理解你的问题,如果不让我知道,我会编辑。

首先,我将提供我认为正在发生的事情以及为什么然后我会尝试给你一个解决方案,尽管我不知道你的用例。

UIStackView的工作方式是为您创建约束。我相信你知道这一点,但让我们一起分析并分析它。在我阅读问题时,在另一个水平堆栈视图中添加水平堆栈视图。在运行时,外部堆栈视图使用固有高度调整内部堆栈视图的大小,然后将约束添加到外部(s1)的centerY。请参阅可视化调试器中的图像。

HorizontalInside

您可以看到它是垂直居中的。要做到这一点,它必须添加一些约束来处理某种类型水平保持水平的缺失Y值。所以现在想想动画。它不是直接改变任何约束,显然改变堆栈视图的对齐不能完全清除原始约束,因为内部堆栈视图无法移动。至少这是我的想法。

如果你让外层栈视图(s1)成为一个垂直的栈视图,那么这就是它在运行时的样子。见图像

Vertical

您可以看到内部堆栈视图(s2)在水平填充之前垂直拉伸以填充整个外部堆栈视图(s1)。就布局和垂直动画的空间而言,情况大不相同。

现在运行动画但是在内部stackview(s2)上使用此代码

@IBAction func changeLayoutDidPress(_ sender: Any) {
    if s2.alignment == .center{
        UIView.animate(withDuration: 10.0, animations: {
            self.s2.alignment = .top
        })
    }else{
        UIView.animate(withDuration: 10.0, animations: {
            self.s2.alignment = .center
        })
    }
}

您将看到内部堆栈视图(s2)移动到s1的顶部。我认为这是因为stackview的内容视图允许它。我希望这能解决你的问题。对不起,我不能完全解释不同的堆栈视图创建的约束,但我知道无论从水平保持水平创建的任何约束必须保持它垂直动画。

更改字体大小的另一个可能原因是它可能导致标签视图重新计算其对stackview的某些内容视图的约束,这将允许它向上移动。只是我的想法。

如果仍然需要水平内部水平,你可以在内部s2上向外部stackview(s1)添加相等的高度,它很可能与上面相同。