【问题标题】:Why does my UIView animate to the wrong position?为什么我的 UIView 动画到错误的位置?
【发布时间】:2013-10-20 04:15:40
【问题描述】:

我在 UIView hardWayView 中有一个 UILabel hardWayLabel。我需要这个视图(以及标签)来动画到屏幕最左侧的一个新位置。然而,当标签移动到正确的位置时,可以看到视图继续远离屏幕左侧。我将以下代码用于动画(我在我的应用程序中成功使用了很多次):

        CGRect frame = hardWayView.frame;
        frame.origin.x = painPoint.x;
        frame.origin.y = painPoint.y;
        hardWayView.frame = frame;
        [UIView beginAnimations:nil context:nil];
        [UIView setAnimationDuration:.25];

我已经使用 NSLog 来确保 painPoint.x 和 painPoint.y 是它们应该是的 9,这可以通过 UILabel 最终位于正确位置的事实得到证实。我想真正的问题是为什么 UIView 会继续移动越过屏幕边界(并且只有在这种情况下,当 UIView 从屏幕中心向左移动时才会这样做)?

我确实启用了自动布局,但我不认为这是罪魁祸首。当我在带有 iOS 7 的 iPhone 模拟器上运行应用程序时会出现此问题,并且我无法让模拟器在 iOS 6 上运行,因此无法将问题隔离到 iOS 7(虽然可能吗?我开始在旧版本的 Xcode 并且该应用程序不使用情节提要)。

这是该问题的屏幕录像。如您所见,将两个视图从左向右移动正常工作。尽管将视图移回左侧时,其中一个视图(黑色背景)似乎从左上角离开屏幕,而标签(橙色文本)则转到正确的位置)。 Explanatory video

更新:这里有更多代码。它与我的应用程序中完美运行的其他部分几乎相同,这有点像大脑冲击波。

NSString *stringOfRands = tDict[@"originalRand"];
if ([stringOfRands rangeOfString:@"+"].location != NSNotFound)
{
     NSArray *arrayOfRands = [stringOfRands componentsSeparatedByString:@" + "];

     for (int z=1; z<[arrayOfRands count]; z++)
     {
          NSString *updateValue = arrayOfRands[z];
          NSInteger newHiddenPosition = [self findBlank:leftSpaces];

          NSDictionary *updateStuff = @{@"updateValue": updateValue, @"workingMasterDict":tDict, @"newPos":@(newHiddenPosition), @"newCGPto":@"left", @"@parent":colorV};

          [self revealHidden:updateStuff];

      } 
}

我相信问题确实发生在调用动画的 revealHidden 方法期间。

[leftSpaces replaceObjectAtIndex:[hardWayPos intValue] withObject:[NSString stringWithFormat:@"full"]];
CGPoint painPoint = [[leftPoints objectAtIndex:[hardWayPos intValue]] CGPointValue];    
[UIView animateWithDuration:0.25 animations:^{
        CGRect frame = hardWayView.frame;
        frame.origin.x = painPoint.x;
        frame.origin.y = painPoint.y;
        hardWayView.frame = frame;
    } completion:^(BOOL finished) {
        //
    }];

hardWayView.hidden=0;
hardWayView.backgroundColor = [UIColor blueColor];
hardWayLabel.textColor = [UIColor orangeColor];

我尝试制作 frame.origin.x.y 实际数字(相对于变量),然后出现相同的模式:UILabel 动画到正确的位置,而 UIView 动画从屏幕的左上角关闭

【问题讨论】:

  • 关闭自动布局并测试它。这可能是罪魁祸首。
  • @Joel 唉,没有。关闭自动布局时也会发生同样的动作。
  • 首先修改帧然后开始动画。
  • @zch,您介意分享您的项目,以便我在最后看看吗?
  • @LuisCien 感谢您抽出宝贵时间。我刚刚在原始问题中添加了更多代码,但我也刚刚将 viewcontroller.h 和 .m 添加到 Github 存储库 github.com/zchr/modx (我真的很抱歉缺乏清洁度,我在上面添加了 ERROR HERE cmets有问题的代码sn-ps。值得注意的一点是重复量。首先这意味着我需要制作更多方法,但其次我认为有趣的是,相同的动画代码在应用程序的其他区域也能正常工作.)

标签: ios objective-c uiview ios-simulator


【解决方案1】:

哇哦!经过muuuch调试,我终于找到了问题! :) 让我告诉你......你有一些有趣的代码。无论如何,您会惊讶地发现这个问题有多愚蠢;你准备好了吗?

问题来了:

在第 540 行附近,您有一个额外的“@”符号,这就是为什么当您尝试检索它无法找到它的值时:

//ERROR HERE
NSArray *arrayOfRands = [stringOfRands componentsSeparatedByString:@" + "];

for (int z=1; z<[arrayOfRands count]; z++)
{
    NSString *updateValue = arrayOfRands[z];
    NSInteger newHiddenPosition = [self findBlank:leftSpaces];

    // This is the line with the error!!
    // You have @"@parent" but it should be @"parent"      
    NSDictionary *updateStuff = @{@"updateValue": updateValue, @"workingMasterDict":tDict, @"newPos":@(newHiddenPosition), @"newCGPto":@"left", @"@parent":colorV};

    [self revealHidden:updateStuff];

}

调试您的代码非常有趣!

干杯:)

【讨论】:

  • 你太棒了。确实这就是问题所在,感谢您抽出宝贵时间来追踪如此愚蠢的错字。我讨厌为要求某人检查我的代码而道歉的前提,但是您调试的那个文件的丑陋构成了一个例外。我告诉自己我只是想编写应用程序,然后清理它/稍后了解 Objective-C ......所以不用说这段代码在未来有很多清理工作。干杯!
  • 真棒 Luis.. 喜欢你对帮助 zch 的奉献精神。 :)
  • @dRAGONAIR 谢谢。这就是为什么我们都在这里......互相帮助
  • @zch,很高兴能够帮助您解决问题。有时有一双额外的眼睛来帮助解决问题是很有用的。此外,您还有一种构建代码的好方法。它确实需要清洁,但你在正确的轨道上。在另一件事上,我之前不想提及任何事情,但是现在赏金期结束了,我想说我投入了时间和精力来解决您的错误;您在赏金期内接受了答案,但没有授予它。我觉得我应得的。如果您不打算奖励它们,请不要提供赏金。这不好。祝你有美好的一天。
  • @zch,完全不用担心。在此期间结束时,我没有看到任何奖励赏金,这就是我留下该评论的原因。但现在我能够看到它。我不确定之前发生了什么。我只是假设这是一个 StackOverflow 错误。无论如何,感谢您接受答案并授予赏金。我希望我能在未来帮助你解决你的另一个问题。干杯!
【解决方案2】:

从外观上看,您在动画开始之前设置了hardWayView.frame = frame;,因此 UIView 将更改位置然后进行动画处理。切换地点

hardWayView.frame = frame;
[UIView beginAnimations:nil context:nil];

应该修复它。

无论如何,我强烈建议您使用动画块。上面的代码应该是这样的:

[UIView animateWithDuration:0.4 animations:^{
CGRect frame = hardWayView.frame;
frame.origin.x = painPoint.x;
frame.origin.y = painPoint.y;
hardWayView.frame = frame;
} completion:^(BOOL finished) {
    //
}];

【讨论】:

  • 感谢您的建议——我将确保用阻塞方法替换所有出现的动画代码。然而,这种变化似乎没有产生效果。无论frame.origin.x.y 设置为什么,问题仍然存在,UIView 仍在屏幕外移动。
【解决方案3】:

在完成块中包含代码不是更好吗? (或在 animateWithDuration 块之前)。

[UIView animateWithDuration:0.25 animations:^{
                CGRect frame = hardWayView.frame;
                frame.origin.x = painPoint.x;
                frame.origin.y = painPoint.y;
                hardWayView.frame = frame;
            } completion:^(BOOL finished) {

            hardWayView.hidden=0;
            hardWayView.backgroundColor = [UIColor blueColor];
            hardWayLabel.textColor = [UIColor orangeColor];

            NSDictionary *hardWay = @{@"view": hardWayView, @"label": hardWayLabel, @"intValue":[NSString stringWithFormat: @"%@", hardWayLabel.text], @"hiddenBool":@0, @"position":@([hardWayPos intValue]), @"originalRand": [NSString stringWithFormat: @"%@", hardWayLabel.text]};
            [masterDict replaceObjectAtIndex:[masterDict indexOfObject:miniMaser] withObject:hardWay];

            }];

此外,如果是我,我也会为每个 rect 使用不同的名称来帮助调试。例如不要总是称你的矩形为“框架”。称之为 centerFrame、leftFrame、rightFrame。

当您在动画结束时注销 hardWayView 的帧时,它会报告您所期望的吗?

当您在动画开始时注销 hardWayView 的帧时,它会报告您所期望的吗?

我的猜测是 hardWayView 的框架不是你想象的那样。

如果您直接设置框架而不进行动画处理,它会按预期工作吗?

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-07-16
    • 1970-01-01
    • 2021-08-20
    相关资源
    最近更新 更多