我目前正在构建一个 UI 插件。这个插件有 2 个图像视图,一个在另一个之上。
当用户在屏幕上滑动时:如果滑动大于某个阈值,则前面的imageView会以与滑动相同的方向离开屏幕,然后出现在后面的imageView后面。
所以我们计划将它用于图像队列。滑动成功后,前面的imageView会离开屏幕,然后居中在后面的ImageView(现在是前面)的后面,然后它会改变里面的图像。
当没有更多图像时,我设置了一个微调器以指示我们正在从服务器下载更多图像。
我们遇到了一个我们自己无法解释的错误——当我们将微调器添加到我们的视图中时,我们的动画出现故障。
滑动后的 imageView 不再离开屏幕而是回到原来的位置。
我们对此感到非常困惑,并确认
[self.view addSubview:spinner];
将导致我们的动画出现意外行为。
附请细动方法:
- (void)move:(UIPanGestureRecognizer *)sender {
CGPoint translatedPoint = [sender translationInView:self.frontView];
if([(UIPanGestureRecognizer*)sender state] == UIGestureRecognizerStateBegan) {
_firstX = self.frontView.center.x;
_firstY = self.frontView.center.y;
}
translatedPoint = CGPointMake(_firstX+translatedPoint.x, _firstY+translatedPoint.y);
[self.frontView setCenter:translatedPoint];
if ([(UIPanGestureRecognizer*)sender state] == UIGestureRecognizerStateEnded) {
// Calculate the if the x-movement is greater than a threshold
float xTravelled = 0;
if (self.frontView.center.x > _firstX)
xTravelled = self.frontView.center.x - _firstX;
else
xTravelled = _firstX - self.frontView.center.x;
// Only move if xTravelled is greater than threshold
if (xTravelled > self.frontView.window.frame.size.width / 3) {
NSLog(@"Swipe detected, currentIndex:%d", currentIndex);
// Lock view from panning until animation is finished.
self.view.userInteractionEnabled = NO;
float newXPosition;
if (self.frontView.center.x > _firstX) {
newXPosition = (float) self.view.frame.size.width * 2;
} else {
newXPosition = (float) -2 * self.view.frame.size.width;
}
// We should trigger a fetch as soon as the back image is empty.
if (![self getBackView].image) {
double delayInSeconds = 2.0;
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, delayInSeconds * NSEC_PER_SEC);
dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
//[self fetchComplete];
[spinner stopAnimating];
[spinner removeFromSuperview];
self.view.userInteractionEnabled = YES;
});
// Pop up spinner if necessary
if (![spinner isAnimating]) {
self.view.userInteractionEnabled = NO;
[spinner setCenter:CGPointMake(_firstX, _firstY)];
[spinner startAnimating];
/* THIS BREAKS OUR ANIMATION - Enable it to see
[self.view addSubview:spinner];
*/
}
}
// Animate the rest of the swipe
[UIView \
animateWithDuration:0.5f delay:0.0f options:UIViewAnimationOptionTransitionNone
animations:^{
// Use smooth animation to move the top image out of the way
[self.frontView setCenter:CGPointMake(newXPosition, self.frontView.center.y)];
}
completion:^(BOOL finished){
// Set it to be physically behind the back image
[self.view sendSubviewToBack:self.frontView];
//[self.frontView setCenter:CGPointMake(_firstX, _firstY)]; // why not necessary??
// Now change the picture
UIImage *next = [self nextImage];
self.frontView.image = next;
// update self.top to reference the new back image
self.frontView = [self getBackView];
// Do not override spinner's block
if (![spinner isAnimating])
self.view.userInteractionEnabled = YES;
}];
} else {
NSLog(@"Swipe NOT detected");
[UIView \
animateWithDuration:0.5f delay:0.0f options:UIViewAnimationOptionAllowUserInteraction
animations:^{
[self.frontView setCenter:CGPointMake(_firstX, _firstY)];
} completion:^(BOOL finished) {
self.view.userInteractionEnabled = YES;
}];
}
}
我知道这相当冗长,但我已将此错误隔离到一个示例项目中,您可以下载并在您的计算机上运行。这个示例项目在这里:http ://bit.ly/WO4cEI
我们怀疑向 self.view 添加子视图会导致 [self.view sendSubviewToBack:self.frontView] 失败。但我们也不确定为什么这会导致我们的动画失败。
谢谢您的帮助!!
编辑
@user2113425 的建议解决了这个问题!!