旋转设备时,动画uiview会切换回原始状态

时间:2014-02-14 15:30:36

标签: ios animation layout uiview rotation

我尝试在IOS7下制作一个小动画。我的视图控制器有2个视图:tableview和mapview。我有一个按钮,可以在“显示地图全屏”和“显示地图和桌面视图”状态之间切换。

这是我的实验代码:

float mapNewX =  self.mapView.frame.origin.x == 0 ? 375 : 0;
float mapNewWidth = mapNewX == 0 ? self.view.frame.size.width : self.view.frame.size.width - mapNewX;

[UIView animateKeyframesWithDuration:0.1 delay:0.0 options:UIViewAnimationCurveEaseOut animations:^
 {
     CGRect mapViewFrame = self.mapView.frame;
     mapViewFrame.origin.x = (mapNewX);
     mapViewFrame.size.width = mapNewWidth;
     self.mapView.frame = mapViewFrame;
 }
completion:^(BOOL finished)
 {
     NSLog(@"OK");
 }];

它可以工作,但是当我旋转设备时,它会切换回原始状态。因此,当我有完整的地图显示时,当旋转设备时,它会切换回屏幕上的tableview + mapview。

如果我通过导航控制器从另一个视图控制器返回,也会发生同样的情况。如果我点击地图引脚的详细信息,它会切换回原始布局。

我该怎么办?非常感谢!

更新:这里是旋转之前/之后的屏幕截图(一些敏感数据被屏蔽掉)

enter image description here

enter image description here

7 个答案:

答案 0 :(得分:6)

如果在旋转或屏幕导航后松开帧更改,则可能与视图控制器的布局方法viewWillLayoutSubviewsviewDidLayoutSubviews或生命周期方法viewWillAppear:viewDidAppear:有关。如果覆盖它们,请检查这些方法的实现。

因为你使用自动布局,所以更好地设置其约束而不是帧。

据我了解,您的任务是移动地图的左侧以显示下方的桌面视图(打开/关闭状态)。使用自动布局,您的屏幕可能看起来很简单:

enter image description here

(UIImageView视图扮演地图的角色)

UITableView约束

  • 恒定宽度约束
  • topview,leading和bottom space to superview constraints设置为零

UIImageView约束

  • 顶视图,底视图和尾随空格,以超级视图约束设置为零
  • 将空格导向 superview 设置为表格宽度(打开状态,为此约束设置动画)

为了实现所需的效果,我们需要将前导空间设置为超视图约束(在屏幕截图中选择)。我们为此约束创建了一个出口,并将其constant属性更改为打开/关闭状态。

@property (weak, nonatomic) IBOutlet NSLayoutConstraint *mapLeadingSpace;

设置菜单的初始状态,然后才会出现在屏幕上。我们设置了默认值,但您可以从NSUserDefaults恢复适当的布尔值设置。

- (void)viewWillAppear:(BOOL)animated
{
    [super viewWillAppear:animated];

    self.mapLeadingSpace.constant = 0; // default is closed
}

接下来,按下按钮上的切换动画。

- (IBAction)toggle:(id)sender
{
    self.mapLeadingSpace.constant = self.mapLeadingSpace.constant == 0
        ? self.tableView.frame.size.width    // opened
        : 0;                                 // closed

    [UIView animateWithDuration:.2 animations:^{
        [self.imageView layoutIfNeeded];
    }];
}

答案 1 :(得分:1)

使用 - (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation

创建一个变量来指示它是全屏幕地图还是拆分视图,然后在旋转完成后运行例程?不确定解决方案是如何高科技的,但这就是我要做的! :)

答案 2 :(得分:1)

我有类似的拆分视图(2个UItableViews),这是我设法修复它的方法。

  • 首先,让一个全局静态变量调用它static BOOL _isViewSplitted 它是静态的,所以当你按或弹出viewContorller留在内存中。

  • 覆盖didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation 检查你的变量在这里,如果是,如果没有则拆分它们,只需返回。

  • 此外,当弹出viewController时,您必须在viewWillAppear中检查(与上面相同)。

答案 3 :(得分:1)

您可以通过编码约束然后设置动画来解决这个问题。

这样的事情(此代码中的值与示例中的值不匹配):

[subview setTranslatesAutoresizingMaskIntoConstraints:NO];
[parentview setTranslatesAutoresizingMaskIntoConstraints:NO];

[parentview addSubview:subview];

NSDictionary *views = NSDictionaryOfVariableBindings(subview);
[parentview addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:[subview]"
                                                                   options:0
                                                                   metrics:nil
                                                                     views:views]];

NSArray *firstConstraints = [NSLayoutConstraint constraintsWithVisualFormat:@"H:[subview]"
                                                                    options:0
                                                                    metrics:nil
                                                                      views:views];
[parentview addConstraints:firstConstraints];
[parentview layoutSubtreeIfNeeded];
[parentview removeConstraints:firstConstraints];

NSArray *secondConstraints = [NSLayoutConstraint constraintsWithVisualFormat:@"H:|-100-[subview]-100-|"
                                                                     options:0
                                                                     metrics:nil
                                                                       views:views];
[parentview addConstraints:secondConstraints];

subview.superview.wantsLayer = YES;
[NSAnimationContext runAnimationGroup:^(NSAnimationContext* context) {
    [context setDuration:.3];
    [context setAllowsImplicitAnimation:YES];
    [context setTimingFunction: [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut]];
    [subview layoutSubtreeIfNeeded];
} completionHandler:^{
        [[self delegate] createOptionMenuForPDFViewWithInvoice:invoice andSuperView:parentview];
}];

答案 4 :(得分:1)

汤姆,你的大问题(恕我直言)是你经常调用你在问题中提供的这段代码。每次它将地图从全屏切换到分割,因为它从现在的位置做出这个决定。你为什么不检查布尔值?您可以在按钮操作中将其翻转以切换地图全屏状态,然后如果您在重定向等上重复调用此代码无关紧要,只需将您在开始时的turnery操作符中的条件更改为此新布尔值而不是查询地图是否全屏

答案 5 :(得分:1)

如果在原帖中提供了以下信息,这个问题更有可能在不需要赏金的情况下相对快速地得到回答(一般来说,这可能是针对iOS中布局相关帖子的一套很好的指导方针):

(1。)是否在故事板中启用了自动布局?

(2。)您使用的是混合(混合)方法还是纯自动布局?换句话说,哪些观点的translatesAutoresizingMaskIntoConstraints设置为YES

(3。)如果覆盖任何布局方法或旋转回调方法,请提供该实现

(4.)向我们展示你的约束

我能够从评论中找到#1的答案。

我的答案很少,我知道这个问题:

如果在地图视图上使用“自动布局”,则在动画块中设置其框架将不会永久地重新定位视图,因为地图视图的约束尚未更改。相反,在动画块之前更新地图视图的约束,然后将layoutIfNeeded发送到动画块内的self.view

// update constraints…

[UIView animateWithDuration:0.5 animations:^{
    [self.view layoutIfNeeded];
}];

答案 6 :(得分:1)

还可以在Viewcontroller类的viewDidload中尝试此操作

if ([self respondsToSelector:@selector(edgesForExtendedLayout)]) {
    self.edgesForExtendedLayout = UIRectEdgeNone;
}