У меня следующая ситуация:
В контроллере представления я создаю произвольное количество прозрачных кнопок UIB, которые переключают появление и исчезновение UIViews над основным видом контроллера. Прямо сейчас, когда вызываются мои методы «увеличения» и «уменьшения», есть код для изменения анимации по умолчанию для двух свойств CALayer (на самом деле это только длительность). Этот код затем вызывается каждый раз, когда происходят действия. Но я бы хотел установить анимационный код один раз внутри слоя, а не использовать его в методах масштабирования. Я объясню больше после того, как я покажу основную идею:
Код создания кнопок / датчиков слишком длинный для размещения (и не имеет отношения к реальному вопросу), но это что-то вроде этого псевдокода:
- (void) createSensors:[number of sensors]
{
for(number of sensors)
{
create UIVIew with some content;
create transparent UIBUtton as sensor and place somewhere in main view;
calculate a transform to "shrink" the UIView's layer to the size and position of the button.
apply transform;
set the UIVIew's layer opacity to 0;
add UIVIew to main view
(but the rest of my interface is in a container view, so I can dim the screen and have this view displayed in a modal-like way.)
do some tagging so the button's tag can later be used to retrieve this view and transform.
}
}
Теперь, когда сенсор нажимается, я выполняю «увеличение» для вида, связанного с сенсором / видом. Я на самом деле приглушаю экран к белому и анимирую положение вида (в действительности слоя) и масштабируем его до центра экрана. И нажав на кнопку в представлении, я делаю наоборот, чтобы отклонить его. Это код:
- (void)animateZoomIn:(UIButton*)sender
{
NSString *sourceTagKey = [NSString stringWithFormat:@"%i",sender.tag];
AnimationSettings *settings = [zoomTransforms objectForKey:sourceTagKey];
UIView *newBox = [[self.view subviews] objectAtIndex:sender.tag];
activeZoomBox = newBox;
CABasicAnimation *a = [CABasicAnimation animation];
a.duration = .4;
[mainCanvas.layer addAnimation:a forKey:@"opacity"];
a = [CABasicAnimation animation];
a.duration = 1;
[activeZoomBox.layer addAnimation:a forKey:@"opacity"];
a = [CABasicAnimation animation];
a.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
a.duration = .5;
[activeZoomBox.layer addAnimation:a forKey:@"transform"];
[mainCanvas setUserInteractionEnabled:NO];
if([settings wantsBackgroundFade])
[mainCanvas.layer setOpacity:.2];
[activeZoomBox.layer setOpacity:1];
[activeZoomBox.layer setTransform:CATransform3DIdentity];
}
- (void)animateZoomOut:(UIButton*)sender
{
NSString *sourceTagKey = [NSString stringWithFormat:@"%i",sender.tag];
AnimationSettings *settings = [zoomTransforms objectForKey:sourceTagKey];
CABasicAnimation *a = [CABasicAnimation animation];
a.duration = .4;
[mainCanvas.layer addAnimation:a forKey:@"opacity"];
a = [CABasicAnimation animation];
a.duration = 1;
[activeZoomBox.layer addAnimation:a forKey:@"opacity"];
a = [CABasicAnimation animation];
a.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
a.duration = .5;
[activeZoomBox.layer addAnimation:a forKey:@"transform"];
[mainCanvas setUserInteractionEnabled:YES];
if([settings wantsBackgroundFade])
[mainCanvas.layer setOpacity:1];
[activeZoomBox.layer setOpacity:0];
[activeZoomBox.layer setTransform:[settings transform]];
}
Итак, вопрос:
Я бы не хотел иметь такой код:
CABasicAnimation *a = [CABasicAnimation animation];
a.duration = .4;
[mainCanvas.layer addAnimation:a forKey:@"opacity"];
в методах действия. Я бы предпочел заменить анимацию один раз и сделать ее «постоянной» для каждого созданного слоя и для представления mainCanvas. Например, я бы предпочел иметь этот код один раз в методе init контроллера и забыть об этом:
CABasicAnimation *a = [CABasicAnimation animation];
a.duration = .4;
NSMutableDictionary *animations = [NSMutableDictionary dictionaryWithDictionary:[mainCanvas.layer actions]];
[animations setObject:a forKey:@"opacity"];
[mainCanvas.layer setActions:animations];
Затем, всякий раз, когда я вызываю [mainCanvas setOpacity:], он будет длиться 0,4 секунды по умолчанию. С CALayer без делегатов это работало бы. Но в этом случае мои слои имеют свои представления как делегаты, которые имеют приоритет над словарем действий, и мне как бы нужны представления как делегаты ..
Так есть ли способ, чтобы слои реагировали на словарь? И если нет, то каким будет лучший способ «навсегда заменить» или добавить анимацию к этим слоям, чтобы анимации содержались в объектах слоя (именно поэтому я предпочел бы не переопределять методы делегата представления для CAAction Протокол)