我正在尝试为注释视图的子视图设置一些子视图。
因此,为了更清楚,灰色图钉是我的注释视图,它有一个不可见的子视图,这个子视图包含这4个彩色圆视图。
annotation view
| invisible view (called typeSelectionView)
| yellow view (called typeButton)
| blue view (called typeButton)
| green view (called typeButton)
| red view (called typeButton)
首先圆圈不可见(变换比例(0,0)及其中心位于灰色针脚的头部),然后,当我选择灰色针脚时,这些圆圈来自针头生长并移动到它们的原始位置(上图中的那个)。
当我取消选择该引脚时,会发生相反的动画。
当我在动画完成之前选择并取消选择(或相反)时,它会改变它的运行方式(如果它正在增长它会收缩)在中间恢复动画。这就是我需要UIViewAnimationOptionBeginFromCurrentState
。
- (void)mapView:(MKMapView *)mapView didSelectAnnotationView:(MKAnnotationView *)annotationView
{
// in case the typeSelectionView was already being showed by another annotationView
if (self.typeSelectionView.superview != annotationView) {
[self.typeSelectionView removeFromSuperview];
[self.typeSelectionView showTypeButtons:NO animated:NO completion:NULL];
}
[annotationView addSubview:self.typeSelectionView];
[self.typeSelectionView showTypeButtons:YES animated:YES completion:NULL];
}
- (void)mapView:(MKMapView *)mapView didDeselectAnnotationView:(MKAnnotationView *)annotationView
{
if (self.typeSelectionView.superview) {
[self.typeSelectionView showTypeButtons:NO
animated:YES
completion:^(BOOL finished) {
if (finished) {
[self.typeSelectionView removeFromSuperview];
}
}];
}
}
- (void)showTypeButtons:(BOOL)show animated:(BOOL)animated completion:(void (^)(BOOL))completion
{
void (^block)(void) = ^{
for (int i = 0; i < self.typeButtons.count; i++) {
TypeButton *typeButton = self.typeButtons[i];
if (show) {
typeButton.center = [self _typeButtonCenterForIndex:i numberOfButtons:self.typeButtons.count];
typeButton.transform = CGAffineTransformIdentity;
} else {
typeButton.center = CGPointMake(viewWidth / 2, viewheight + 5); // pin head center
typeButton.transform = CGAffineTransformMakeScale(0, 0);
}
}
};
if (animated) {
[UIView animateWithDuration:0.5
delay:0
options:UIViewAnimationOptionBeginFromCurrentState
animations:block
completion:^(BOOL finished) {
if (completion) {
completion(finished);
}
}];
} else {
block();
if (completion) {
completion(YES);
}
}
}
到目前为止没问题,但是当一个灰色引脚显示typeSelectionView(如上图所示)然后我选择另一个引脚时,就像这部分一样:
if (self.typeSelectionView.superview != annotationView) {
[self.typeSelectionView removeFromSuperview];
[self.typeSelectionView showTypeButtons:NO animated:NO completion:NULL];
}
什么也没做。
4个圆圈简单地从一个引脚跳到另一个引脚而没有任何动画。
我期望的是[self.typeSelectionView showTypeButtons:NO animated:NO completion:NULL];
将这些按钮设置为“隐藏”(缩放(0,0)并且在引脚的头部中心)没有任何动画(因为隐形视图没有超视图再这样,所以他们甚至没有显示),然后当我用[annotationView addSubview:self.typeSelectionView];
将typeSelectionView添加到新的annotationView时,我使用[self.typeSelectionView showTypeButtons:YES animated:YES completion:NULL];
再次将圆圈设置为原始位置。
顺便说一下,在[typeButton.layer removeAllAnimations]
开头做showTypeButtons:animated:completion:
什么也没做。
我该如何解决这个问题?
提前致谢。
编辑:(如果有人可以向我解释这个问题并帮助我解决,可以获奖)=)
假设圆圈如上图所示,那么这段代码:
NSLog(@"type selected");
[self.typeSelectionView showTypeButtons:NO
animated:YES
completion:^(BOOL finished) {
NSLog(@"finisheddddd: %d", finished);
}];
[self.typeSelectionView showTypeButtons:NO
animated:YES
completion:^(BOOL finished) {
NSLog(@"finished: %d", finished);
}];
生成以下输出:
type selected
finished: 1
finisheddddd: 1
所以第二个动画首先结束,两个动画都以finished == YES
结束。
第二个动画(首先完成)也会立即结束,而不是在动画结束后结束。
O.o
答案 0 :(得分:-1)
检查我写的代码但未经过测试。请试用它来获得结果
- (void)mapView:(MKMapView *)mapView didDeselectAnnotationView:(MKAnnotationView *)annotationView
{
if (self.typeSelectionView.superview)
{
[self.typeSelectionView showTypeButtons:NO
animated:YES
completion:^(BOOL finished) {
if (finished) {
[self.typeSelectionView removeFromSuperview];
}
}];
}
}
- (void)showTypeButtons:(BOOL)show animated:(BOOL)animated completion:(void (^) (BOOL))completion
{
[UIView animateWithDuration:(animated) ?0.5f : 0.0f
delay:(self.animationStarted)? 0.5 : 0.0
options:UIViewAnimationOptionBeginFromCurrentState
animations:^{
self.animationStarted = YES;
[self setButtonVisible:show];
}
completion:^(BOOL finished) {
self.animationStarted = NO;
if (completion) {
completion(finished);
}
}];
}
-(void)setButtonVisible:(BOOL)visible
{
[self.typeButtons enumerateObjectsUsingBlock:^(TypeButton typeButton, NSUInteger idx, BOOL *stop) {
if (visible)
{
typeButton.center = [self _typeButtonCenterForIndex:idx numberOfButtons:self.typeButtons.count];
typeButton.transform = CGAffineTransformIdentity;
}
else
{
typeButton.center = CGPointMake(viewWidth / 2, viewheight + 5); // pin head center
typeButton.transform = CGAffineTransformMakeScale(0, 0);
}
}];
}
答案 1 :(得分:-1)
原来问题是,当我将typeButtons设置为非动画时,它们不会立即重绘,所以它们不会改变它们的当前状态,所以会发生什么:
one mapView:didSelectAnnotationView: method call:
- show the buttons animated
***redraw cycle here***
another mapView:didSelectAnnotationView: method call:
- hide the buttons non-animated
(no redraw cycle here, so buttons are still showing)
- show the buttons animated
所以我提出了这个糟糕的解决方案:
- (void)showTypeButtons:(BOOL)show animated:(BOOL)animated completion:(void (^)(BOOL))completion
{
void (^block)(void) = ^{
for (int i = 0; i < self.typeButtons.count; i++) {
TypeButton *typeButton = self.typeButtons[i];
if (show) {
typeButton.center = [self _typeButtonCenterForIndex:i numberOfButtons:self.typeButtons.count];
typeButton.transform = CGAffineTransformIdentity;
} else {
typeButton.center = CGPointMake(viewWidth / 2, viewheight + 5); // pin head center
typeButton.transform = CGAffineTransformMakeScale(0, 0);
}
}
};
if (animated) {
[UIView animateWithDuration:0.5
delay:0
options:self.typeButtonsChangedWithoutAnimation ? 0 : UIViewAnimationOptionBeginFromCurrentState
animations:block
completion:^(BOOL finished) {
if (completion) {
completion(finished);
}
}];
self.typeButtonsChangedWithoutAnimation = NO;
} else {
self.typeButtonsChangedWithoutAnimation = YES;
block();
if (completion) {
completion(YES);
}
}
}
如果没有UIViewAnimationOptionBeginFromCurrentState
,动画将从其实际状态开始,而不是从其绘制状态开始。
我发现但无效的一个解决方案是:What is the most robust way to force a UIView to redraw? 即使它确实有效,我也不想要它......
是的,我不会接受这个答案,因为它很糟糕。 它实际上并没有解决我的问题,即改变当前状态,而不是通过它。 我只是张贴它以防有人看到并了解如何真正解决我原来的问题。