我目前正在构建一个UI插件。这个插件有2个imageViews,一个在另一个之上。
当用户在屏幕上滑动时:如果滑动大于阈值,则前面的imageView将使屏幕与滑动方向相同,然后显示在后面的imageView后面。
因此我们计划将其用于图像队列。成功滑动后,前面的imageView将离开屏幕,然后居中于backImageView(现在是前面)后面,然后它会更改内部的图像。
当没有更多图像时,我设置了一个微调器,表示我们正在从服务器下载更多图像。
我们遇到了一个我们无法解释的错误 - 当我们将微调器添加到视图中时,我们的动画出现故障。
刷过的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的建议解决了这个问题!!
答案 0 :(得分:1)
首先,您无需在此时添加微调器。
- (void)viewDidLoad
{
[super viewDidLoad];
UIPanGestureRecognizer *panRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(move:)];
[panRecognizer setMinimumNumberOfTouches:1];
[panRecognizer setMaximumNumberOfTouches:1];
[panRecognizer setDelegate:self];
[self.view addGestureRecognizer:panRecognizer];
self.view.userInteractionEnabled = YES;
// Index starts at zero so we pick even.
self.frontView = self.evenImage;
// Setting the images
images = [[NSArray alloc] initWithObjects:@"a.jpeg", @"b.jpeg", nil]; // @"c.jpeg", @"d.jpeg", @"e.jpeg", nil];
currentIndex = 0;
self.evenImage.image = [self nextImage];
self.oddImage.image = [self nextImage];
// Spinner
spinner = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhiteLarge];
**spinner.hidesWhenStopped = YES;
[self.view addSubview:spinner];**
}
你可以在viewDidLoad中添加微调器并设置hidesWhenStopped来隐藏它,并在移动函数中删除[spinner removeFromSuperview];这一行。
addSubView的问题在于它改变了子视图的zorder,它可能涉及但不确定..
有很多方法可以解决这个问题。
答案 1 :(得分:0)
原因可能是微调器的动画。当viewController包含一个刷新高频的tableView时会出现同样的现象。图层的重绘会打破动画。根据视图的子视图来调整微调器,使这种现象发生。