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

How to programmatically animate the alignment property of an UIStackView in ios 9

我想知道如何为水平 UIStackView 的对齐方式 属性 设置动画,例如从 UIStackViewAlignmentCenter 到 UIStackViewAlignmentTop,反之亦然,我想同时直观地反映这种变化。

编辑:

我有:

这是我的视图层次结构:

我想做的事情:

我想在触摸按钮 b1 时将 S1 的对齐方式从 "Center" 更改为 "Top",并且我想为该更改设置动画。

我试过的

- (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];
}

None 这些选项有效。对齐方式发生了变化,但 UI 并未反映它,也没有为任何动画设置动画。如果我更改轴的对齐方式(尝试将轴从水平更改为垂直,反之亦然),一切都会顺利进行。如果我动态地更改两个标签中使用的字体大小,一切顺利,问题出在 stackView 的对齐方式上。但是根据苹果文档,对齐 属性 是可动画的,所以我做错了什么??

有人可以帮帮我吗??

提前致谢

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

首先,我将提供我认为正在发生的事情以及原因,然后我将尝试为您提供解决方案,尽管我不知道您的用例。

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

你可以看到它是垂直居中的。为此,它必须添加一些约束来处理缺失的某种类型水平保持水平的 Y 值。所以现在想到动画。它没有直接更改任何约束,并且显然更改堆栈视图的对齐方式不能完全清除原始约束,因为内部堆栈视图无法移动。至少这是我认为正在发生的事情。

有趣的是,如果您将外部 stackview(s1) 设为垂直 stackview,这就是 运行 时的样子。看图

你可以看到内部stackview(s2)在水平填充之前被垂直拉伸以填充整个外部stackview(s1)。就布局和垂直动画的空间而言有很大不同。

现在运行使用这段代码在内部堆栈视图(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
        })
    }
}

您将看到内部 stackview(s2) 移动到 s1 的顶部。我认为这是因为 stackview 的内容视图允许它。我希望这能解决您的问题。抱歉,我无法完全解释由不同堆栈视图创建的约束,但我知道无论从 Horizo​​ntal 持有水平创建的约束必须防止它垂直动画。

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

如果仍然需要在 Horizo​​ntal 内部设置 Horizo​​ntal,您可以在内部 s2 上向外部 stackview(s1) 添加相同的高度,它很可能会像上面一样工作。