- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我刚从 iOS 7.1 切换到 iOS 8.1。 UIView animateWithDuration
遇到以下问题。图片值一千字,我制作了每个 iOS 下行为的视频:
iOS 7.1:
iOS 8.1:
这是一个 iPhone 应用程序。
我应该注意,我在发帖前已经搜索过 SO 和其他地方。这似乎是一个公认的问题,但我发现有一些关于“使用基于约束的动画”(我不明白)和关闭自动布局的引用,但没有真正的共识。
我已经尝试了几次刺伤,但一无所获。如果有人可以指出(或引导我完成)明确的修复,我将不胜感激。
我应该提一下,该应用程序只能在纵向位置工作,所以我在开发过程中没有考虑自动布局。
所有涉及的 View 都是以编程方式创建的,滚动条本身除外。
这是代码。我包括了整个方法,这很长,但我真的不明白新 iOS 中发生了什么变化,所以为了安全起见。 animateWithDuration
调用非常深入到代码块中:
-(void) displayDayChart
{
[self.scroller setBackgroundColor:[UIColor clearColor]];
UIImage *image = [UIImage imageNamed:@"GrayPaper.png"];
self.chartView.backgroundColor = [UIColor colorWithPatternImage:image];
[self.view addSubview:self.scroller];
[self.scroller setScrollEnabled:YES];
[self.scroller setContentSize:CGSizeMake(320, 1800)];
[self.scroller setContentOffset:CGPointMake(0.0, 0.0) animated:YES];
dayBarArray = [[NSMutableArray alloc]init];
infoLabelArray = [[NSMutableArray alloc]init];
timeLabelArray = [[NSMutableArray alloc]init];
timeFrameDC = - 86400; // 24 hours for this test, selectable in real life
[self.scroller.subviews makeObjectsPerformSelector: @selector(removeFromSuperview)];
timeframeDCStart = [NSDate dateWithTimeIntervalSinceNow:timeFrameDC];
timeframeDCEnd = [timeframeDCStart dateByAddingTimeInterval:abs(timeFrameDC)];
actPredicate = [NSPredicate predicateWithFormat:@"(startTime >= %@ AND stopTime <= %@) OR ((startTime <= %@ AND stopTime >= %@) OR (startTime <= %@ AND stopTime == NULL))",timeframeDCStart,timeframeDCEnd,timeframeDCStart,timeframeDCStart,timeframeDCEnd];
NSFetchedResultsController *dayActivityFRC = [TimedActivity MR_fetchAllSortedBy:@"startTime" ascending:YES withPredicate:actPredicate groupBy:nil delegate:nil];
double taDuration;
double activityPercent;
int barHeight;
int lastHeight = 0;
int tickerCount = 1;
int barY;
int lastBarY = 0;
CGRect lastBarFrame;
#pragma mark DisplayDayChart setup
for (TimedActivity *activity in dayActivityFRC.fetchedObjects)
{
// Create bar and associated labels
thisBar = [[DayChartBar alloc] initWithFrame:CGRectZero];
thisInfoLabel = [[UILabel alloc]initWithFrame:CGRectZero];
thisTimeLabel = [[UILabel alloc]initWithFrame:CGRectZero];
arrowView = [[UIView alloc]initWithFrame:CGRectZero];
thisBar.tag = tickerCount;
thisInfoLabel.tag = thisBar.tag + 100;
thisTimeLabel.tag = thisBar.tag + 200;
arrowView.tag = thisBar.tag + 300;
UIImage *image = [UIImage imageNamed:@"LeftArrowRed.png"];
// Add them to the scroller
[self.scroller addSubview:thisBar];
[self.scroller addSubview:thisInfoLabel];
[self.scroller addSubview:thisTimeLabel];
[self.scroller addSubview:arrowView];
NSCalendar *calendar = [NSCalendar currentCalendar];
if (!activity.stopTime) // Currently running
{
if ([activity.startTime timeIntervalSinceDate:timeframeDCStart] < 0)
{
dayBarDurationString = @"24:00:00";
taDuration = (fabs([timeframeDCStart timeIntervalSinceDate:timeframeDCEnd]));
}
else
{
NSDateComponents *components= [calendar components:NSDayCalendarUnit|NSHourCalendarUnit|NSMinuteCalendarUnit|NSSecondCalendarUnit fromDate:activity.startTime toDate:timeframeDCEnd options:0];
NSInteger hours = [components hour];
NSInteger minutes = [components minute];
NSInteger seconds =[components second];
dayBarDurationString = [NSString stringWithFormat:@"%02li:%02li:%02li",(long)hours,(long)minutes,(long)seconds];
taDuration = (fabs([activity.startTime timeIntervalSinceDate:timeframeDCEnd]));
}
}
else // Either early edge case or fully encapsulated
{
if ([activity.startTime timeIntervalSinceDate:timeframeDCStart] < 0) // Early edge case
{
NSDateComponents *components= [calendar components:NSDayCalendarUnit|NSHourCalendarUnit|NSMinuteCalendarUnit|NSSecondCalendarUnit fromDate:timeframeDCStart toDate:activity.stopTime options:0];
NSInteger hours = [components hour];
NSInteger minutes = [components minute];
NSInteger seconds =[components second];
dayBarDurationString = [NSString stringWithFormat:@"%02li:%02li:%02li",(long)hours,(long)minutes,(long)seconds];
taDuration = (fabs([activity.stopTime timeIntervalSinceDate:timeframeDCStart]));
}
else if ([activity.startTime timeIntervalSinceDate:timeframeDCStart] > 0) // Encapsulated
{
NSDateComponents *components= [calendar components:NSDayCalendarUnit|NSHourCalendarUnit|NSMinuteCalendarUnit|NSSecondCalendarUnit fromDate:activity.startTime toDate:activity.stopTime options:0];
NSInteger hours = [components hour];
NSInteger minutes = [components minute];
NSInteger seconds =[components second];
dayBarDurationString = [NSString stringWithFormat:@"%02li:%02li:%02li",(long)hours,(long)minutes,(long)seconds];
taDuration = [activity.duration doubleValue];
}
}
NSDateFormatter *localDateFormatter = [[NSDateFormatter alloc] init];
[localDateFormatter setDateFormat:@"MMM dd"];
NSDateFormatter *localTimeFormatter = [[NSDateFormatter alloc] init];
[localTimeFormatter setDateFormat:@"hh:mm a"];
NSString * timeLabelDateString = [[NSString alloc]init];
NSString * timeLabelTimeString = [[NSString alloc]init];
NSString * timeLabelString = [[NSString alloc]init];
if (([activity.startTime timeIntervalSinceDate:timeframeDCStart] < 0))
{
timeLabelDateString = [localDateFormatter stringFromDate:timeframeDCStart];
timeLabelTimeString = [localTimeFormatter stringFromDate:timeframeDCStart];
}
else
{
timeLabelDateString = [localDateFormatter stringFromDate:activity.startTime];
timeLabelTimeString = [localTimeFormatter stringFromDate:activity.startTime];
}
timeLabelString = [NSString stringWithFormat:@"%@ - %@",timeLabelDateString,timeLabelTimeString];
thisBar.endColor = activity.color;
activityPercent = fabs((taDuration / timeFrameDC) * 100);
if (activityPercent > 100)
{
activityPercent = 100;
}
if (activityPercent < 1.9)
{
activityPercent = 1.9;
}
barHeight = abs((self.scroller.contentSize.height - 100) * (activityPercent / 100));
if (tickerCount == 1)
{
barY = self.scroller.contentSize.height -10;
}
else
{
barY = (lastBarY - lastHeight);
}
#pragma mark DisplayDayChart animation
[UIView animateWithDuration:.8
delay:0.0
options: UIViewAnimationCurveEaseInOut // Deprecated, but still works
animations:^
{
// Starting state *************************************
thisBar.frame = CGRectMake(20, self.scroller.contentSize.height, 130, 0);
thisBar.backgroundColor = [UIColor blackColor];
thisInfoLabel.frame = CGRectMake(20, self.scroller.contentSize.height, thisBar.frame.size.width, 30);
thisTimeLabel.frame = CGRectMake((thisBar.frame.origin.x) + (thisBar.frame.size.width + 35), self.scroller.contentSize.height, 150, 15);
thisTimeLabel.textColor = [UIColor blueColor];
arrowView.frame = CGRectMake(thisTimeLabel.frame.origin.x - 20, thisTimeLabel.frame.origin.y, 16, 16);
thisInfoLabel.textColor = [UIColor clearColor];
// End state *************************************
thisBar.frame = CGRectMake(20, barY, 130, - barHeight);
thisBar.backgroundColor = thisBar.endColor;
thisBar.layer.shadowColor = [[UIColor blackColor] CGColor];
thisBar.layer.frame = CGRectInset(thisBar.layer.frame, 0.0, 3.0);
thisBar.layer.shadowOpacity = 0.7;
thisBar.layer.shadowRadius = 4.0;
thisBar.layer.shadowOffset = CGSizeMake(5.0f, 5.0f);
// Position infoLabel
thisInfoLabel.frame = CGRectMake(20, self.scroller.contentSize.height + ((thisBar.frame.size.height / 2) - 30), thisBar.frame.size.width, 30);
thisTimeLabel.frame = CGRectMake((thisBar.frame.origin.x) + (thisBar.frame.size.width + 35), (thisBar.frame.origin.y) + (thisBar.frame.size.height) - 5, 150, 15);
thisInfoLabel.textColor = [UIColor blackColor];
dayBarNameString = activity.name;
[thisInfoLabel setFont:[UIFont fontWithName:@"Noteworthy-Bold" size:16.0]];
thisInfoLabel.numberOfLines = 0;
thisInfoLabel.textAlignment = NSTextAlignmentCenter;
// thisInfoLabel.layer.borderWidth = 1;
thisInfoLabel.text = [NSString stringWithFormat:@"%@\n%@",dayBarNameString,dayBarDurationString];
[thisInfoLabel sizeToFit];
if ( thisInfoLabel.frame.size.height >= thisBar.frame.size.height)
{
thisInfoLabel.text = [NSString stringWithFormat:@"%@",dayBarNameString];
}
else
{
thisInfoLabel.text = [NSString stringWithFormat:@"%@\n%@",dayBarNameString,dayBarDurationString];
}
[thisInfoLabel sizeToFit];
[thisInfoLabel setHidden:NO];
thisInfoLabel.center = thisBar.center;
arrowView.frame = CGRectMake(thisTimeLabel.frame.origin.x - 20, thisTimeLabel.frame.origin.y, 16, 16);
arrowView.backgroundColor = [UIColor colorWithPatternImage:image];
thisTimeLabel.textColor = [UIColor blueColor];
[thisTimeLabel setFont:[UIFont boldSystemFontOfSize:13]];
thisTimeLabel.numberOfLines = 0;
thisTimeLabel.textAlignment = NSTextAlignmentLeft;
thisTimeLabel.text = timeLabelString;
[thisTimeLabel sizeToFit];
}
completion:^(BOOL finished)
{
[self repositionLabels];
}];
[dayBarArray addObject:thisBar];
[infoLabelArray addObject:thisInfoLabel];
[timeLabelArray addObject:thisTimeLabel];
taDuration = 0;
tickerCount ++;
lastBarY = barY;
lastHeight = barHeight;
lastBarFrame = thisBar.frame;
[self positionInitialDayBarView];
}
}
最佳答案
好的,首先。拒绝使用 Interface Builder,您将失去很多方便的东西。这就像在说“我只使用 Xcode 3,因为它曾经为我工作,所以我就保留了它。”。 Interface Builder 是一款很棒的工具,可以让创建 UI 变得异常简单。
实际问题
你说你没有使用 AutoLayout。这是不正确的。
默认行为(肯定在 iOS8 中,我认为在 iOS7 中)是当你创建一个 UIView
(或任何 UI 元素)并将其添加到 View 时,系统将采用 自动调整大小掩码
并应用自动布局约束以匹配调整大小掩码。
这意味着当你做...
UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(10, 10, 100, 21)];
[self.view addSubView:label];
然后标签添加了自动布局约束以将其固定到位置 (10, 10) 和大小 (100, 21)。
然后你不能通过做...来改变框架
label.frame = CGRectMake(10, 50, 100, 21);
因为自动布局约束会把它放回到它开始的地方。
解决方案
有两种解决方案。
正确的解决方案是学习如何使用 AutoLayout。它已经存在 3 年了,并且对 iOS 开发变得越来越重要(即使只是在纵向 iPhone 应用程序上,您现在也有 4 种不同的设备尺寸需要处理)。如果你不开始学习 AutoLayout,你就会落在后面。现在,这几乎是所有 iOS 开发的必要条件。
不正确且非常非常糟糕的解决方案是阻止系统添加这些约束。您可以通过添加行...
label.translatesAutoresizingMaskIntoConstraints = NO;
在创建标签(以及所有其他界面元素)之后。
这将阻止添加这些自动约束并阻止它们干扰您的布局。
虽然这是错误的解决方案。如果您这样做,您只是在推迟必须学习自动布局的时间点。
关于ios - UIView animateWithDuration 在 iOS 8 中表现不同,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27385681/
我正在使用这些(代码块 1 和 2)将带有动画的 UIScrollView 从开始移动到我的结束点(x:0 到 1000,在这个例子中) 代码块 1: UIScrollView.animateWith
-(void)fadeLabel{ UILabel *label = (UILabel *)[self.view viewWithTag:kLabelTag]; [UIView ani
我正在使用 animateWithDuration 让我的 UIVIew 之一无休止地旋转。现在,我需要获取 UIView 在特定时间旋转的当前值。我尝试使用以下功能: -(float)getCurr
我在 viewController 中有一个循环动画 - (void)moveAnimating { [UIView animateWithDuration:2.0f animations:^
出于某种原因,如果我只使用代码: [UIView animateWithDuration:.5 delay:0 options:UIViewAn
我正在学习 Swift,但在从不同函数移动 UIView 时遇到问题。如果我使用这个: View Controller : let boardView = BoardView() @IBAction
let downFrame = CGRect(x: 0, y: ScreenSize.height, width: ScreenSize.width, height: ScreenSize.heigh
我试图让“luke”跳过一个物体以确保游戏不会结束,他确实这样做了,但即使他避开了物体,游戏仍然会结束,就好像 luke 在游戏过程中没有离开他原来的位置一样动画。 我在 -(void)touches
我在 UIViewController 中使用此方法来显示一条消息三秒钟,然后淡出。 mainMessageLabel 是在接口(interface)文件中声明的 UILabel。 - (void)
我正在尝试对三个 UILabel(display1、display2、display3)进行交叉溶解,方法是使用 block 动画淡出、更改文本,然后一次淡入一个。我使用的代码是: [UIView a
今天 animateWithDuration 表现得很愚蠢,我不知道为什么。我检查了所有的东西,所有的括号,一切都很完美,但它总是呈现我没有指定为动画的代码行。 好的,这就是重点。我有一个 longP
我有一个没有自动布局的 ViewController,我正在尝试为一些按钮设置动画。我在 ViewDidAppear 中有一些 UIView animateWithDuration 代码,那里的一切都
我想在我的标签上先淡出然后淡入,我可以让两者分开工作但不能一起工作。 [UILabel animateWithDuration:1.0 animations:^{ _swixV
我正在尝试运行示例来测试此功能。我在 Storyboard中有一个标签和一个按钮,我在 View Controller 中引用了标签的底部约束。当我使用按钮时,我希望标签随动画一起移动,但它在没有动画
我有一个用 animateWithDuration 和 setAnimationRepeatCount() 动画的脉冲矩形。 我正在尝试在同步“点击”的动画 block 中添加声音效果。但音效只播放一
我在 switch 语句中有一段动画,该语句运行并执行预期的操作。在计时器内每二十秒成功调用一次动画。但是,动画不会在任何时候发生,而是在第一次发生。在我下面的代码中,您将看到我用来尝试突出显示问题的
我正在尝试将 JSSAlertView ( github.com/stakes/JSSAlertView ) 与 Swift 2.0 一起使用,但出现错误: Cannot invoke animate
我在我的 ScrollView 委托(delegate)方法 scrollViewDidEndDragging 中执行了一个简单的动画。 看起来像这样: - (void)scrollViewDidEn
我有一个 CollectionView,我想在用户选择的 CollectionViewCell 中创建一个动画。我选择使用 animateKeyframesWithDuration 是因为我想逐步创建
在执行 UIView.animateWithDuration 时,我想定义一条自定义曲线以方便使用,而不是默认曲线:.CurveEaseInOut、.CurveEaseIn、.CurveEaseOut
我是一名优秀的程序员,十分优秀!