Есть ли способ придать словарю действий CALayer постоянный приоритет над его делегатом UIView? - PullRequest
1 голос
/ 29 января 2012

У меня следующая ситуация:

В контроллере представления я создаю произвольное количество прозрачных кнопок 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 Протокол)

1 Ответ

0 голосов
/ 29 января 2012

Почему бы просто не переопределить -actionForLayer:forKey: в UIView, чтобы предоставить нужное действие для важных клавиш (и вызвать super для остальных)?Невозможно изменить приоритет, поэтому ваши единственные варианты - реализовать -actionForLayer:forKey: или использовать ручную анимацию.

...