简体   繁体   English

如何在iOS 9中以编程方式为UIStackView的对齐方式设置动画

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

I want to know how can I animate a change in the alignment property of an horizontal UIStackView say from UIStackViewAlignmentCenter to UIStackViewAlignmentTop and vice versa, and I want to visually reflects this change at the same time. 我想知道如何为从UIStackViewAlignmentCenter到UIStackViewAlignmentTop的水平UIStackView的对齐属性进行动画处理,反之亦然,并且我想在视觉上同时反映此更改。

EDIT: 编辑:

What I have: 我有的:

This is my hierarchy of views: 这是我的视图层次结构:

  • two buttons named b1 and b2; 两个名为b1和b2的按钮; b1 has an action named "changeAlignmentToTop" and b2 has an action named "changeAlignmentToCenter", which are activated Upon touch Up Inside in the respective button. b1有一个名为“ changeAlignmentToTop”的动作,b2有一个名为“ changeAlignmentToCenter”的动作,在相应按钮中触摸Up Inside时激活。
  • an UIView named Pview with frame (0,100,414,100). 一个名为Pview且框架为(0,100,414,100)的UIView。
    • an horizontal UIStackView named S1, with the alignment property set as "center". 一个名为S1的水平UIStackView,其对齐方式属性设置为“ center”。 This stackView has been pinned to the borders of pView. 此stackView已固定到pView的边界。
      • an horizontal UIStackView named S2, with the alignment property set as "Fill" and which has inside two labels. 一个名为S2的水平UIStackView,其对齐方式属性设置为“填充”,并且内部有两个标签。

What I want to do: 我想做的事:

I want to change the alignment of S1 from "Center" to "Top" when I touch the button b1 and I want to animate that change. 我想在触摸按钮b1并将动画设置为动画时将S1的对齐方式从“中心”更改为“顶部”。

What I tried 我尝试了什么

- (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 of these options work. 这些选项均无效。 The aligment change but the UI does not reflects it neither it animates anything. 适应性更改,但UI均未反映该变化,也没有为任何动画设置。 If I change the alignment for axis (trying to change the axis from horizontal to vertical and vice versa) every things goes well. 如果我更改轴的对齐方式(尝试将轴从水平方向更改为垂直方向,反之亦然),一切都会顺利进行。 If I change animatedly the size of the font used in both label every thing goes well, the problem is with the alignment of the stackView. 如果我动画地改变两个标签中使用的字体大小,一切都会顺利进行,那么问题就在于stackView的对齐方式。 but according to the apple documentation the alignment property is animatable, so what I'm doing wrong?? 但是根据苹果的文档,alignment属性是可动画的,所以我在做什么错?

Can anybody please help me?? 有人可以帮我吗?

Thanks in advance 提前致谢

So hopefully I understand your question and if not let me know and I will edit. 因此,希望我能理解您的问题,如果不告诉我,我会进行编辑。

First I will offer what I think is happening and why and then I will try to give you a solution although I don't know your use case. 首先,我将提供我认为正在发生的事情以及原因,然后我将尝试为您提供解决方案,尽管我不知道您的用例。

The way UIStackView works is to create constraints for you. UIStackView的工作方式是为您创建约束。 I am sure you know this but let's take your stack and analyze it together. 我相信您知道这一点,但让我们将您的堆栈进行分析。 Adding a horizontal stackview inside another horizontal stackview as I read the question. 在阅读问题时,在另一个水平stackview中添加了一个水平stackview。 At run time the outer stackview sizes the inner stackview with intrinsic height then adds constraints to the centerY of the outer(s1). 在运行时,外部stackview用内部高度调整内部stackview的大小,然后将约束添加到external(s1)的centerY。 See image from visual debugger. 从可视调试器查看图像。

Horizo​​ntalInside .

You can see it is vertically centered. 您可以看到它垂直居中。 To do this it must add some constraints to deal with a missing Y value of some type horizontal holding horizontal. 为此,它必须添加一些约束以处理某些水平保持水平的Y值丢失。 So now think of the animation. 所以现在考虑动画。 It is not directly changing any constraints and apparently changing the alignment of a stackview must not completely clear the original constraints as the inner stackview is unable to move. 它不会直接更改任何约束,并且显然更改堆栈视图的对齐方式一定不能完全清除原始约束,因为内部堆栈视图无法移动。 At least this is what I think is going on. 至少这是我所想的。

So interestingly enough if you make the outer stackview(s1) a vertical stackview this is what it looks like at run time. 非常有趣的是,如果将外部stackview(s1)设置为垂直stackview,则这就是运行时的外观。 see image 看图片

垂直

You can see that the inner stackview(s2) is stretched vertically to fill the entire outer stackview(s1) before it was horizontally filled. 您会看到内部stackview(s2)在垂直填充之前已被拉伸,以在水平填充之前将整个外部stackview(s1)填充。 Much different as far as layout and room to animate vertically. 垂直布局的布局和空间差异很大。

Now running the animation But on the inner stackview(s2) with this code 现在运行动画,但是使用此代码在内部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
        })
    }
}

You will see the inner stackview(s2) move to the top of s1. 您将看到内部stackview(s2)移至s1的顶部。 I think this is because of the content view of the stackview allowing it. 我认为这是因为stackview的内容视图允许它。 I hope this solves your issue. 我希望这能解决您的问题。 Sorry I cannot fully explain the constraints created by the different stackviews but I know that whatever constraints are created from Horizontal holding a horizontal must keep it from animating vertically. 抱歉,我无法完全解释由不同的stackview创建的约束,但是我知道无论是从Horizo​​ntal保持水平创建的约束都必须防止其垂直动画。

Also a possible reason that changing the font size works is that it is probably causing the label view to recalculate its constraints to some content view of the stackview which would allow it to move up. 更改字体大小的可能另一个原因是,它可能导致标签视图重新计算其对stackview的某些内容视图的约束,这将使它向上移动。 Just my thoughts on it. 只是我的想法。

If having Horizontal inside Horizontal is still needed you could add equal heights to outer stackview(s1) on the inner s2 and it would most likely work the same as above. 如果仍然需要在内部“水平”内添加“水平”,则可以在内部s2上的外部stackview(s1)中添加相同的高度,并且很有可能与上述相同。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM