2014-11-24 5 views
6

Когда открывается представление контроллера просмотра, я хочу запустить анимацию, в которой все элементы в контроллере представления скользят извне в нижней части экрана в их естественные позиции. Для этого я subview.frame.origin.y += self.view.frame.size.height в viewDidLayoutSubviews. Я также пробовал viewWillAppear, но он вообще не работает. Затем я оживляю их до своих естественных позиций с subview.frame.origin.y -= self.view.frame.size.height в viewDidAppear.Изменение рамки в viewDidLayoutSubviews

Проблема заключается в том, что viewDidLayoutSubviews вызывается несколько раз в течение всей продолжительности жизни контроллера. Таким образом, когда такие вещи, как показ клавиатуры, все мой контент снова заменяется вне представления.

Есть ли лучший способ для этого? Нужно ли добавлять какой-то флаг, чтобы проверить, запущена ли анимация?

EDIT: вот код. Здесь я звоню prepareAppearance в viewDidLayoutSubviews, который работает, но viewDidLayoutSubviews вызывается несколько раз в течение всего срока службы контроллера.

- (void)viewDidLayoutSubviews 
{ 
    [super viewDidLayoutSubviews]; 
    [self prepareAppearance]; 
} 

- (void)viewDidAppear:(BOOL)animated 
{ 
    [super viewDidAppear:animated]; 
    [self animateAppearance]; 
} 


- (NSArray *)animatableViews 
{ 
    return @[self.createAccountButton, self.facebookButton, self.linkedInButton, self.loginButton]; 
} 

- (void)prepareAppearance 
{ 
    NSArray * views = [self animatableViews]; 
    NSUInteger count = [views count]; 

    for (NSUInteger it=0 ; it < count ; ++it) { 

     UIView * view = [views objectAtIndex:it]; 
     CGRect frame = view.frame; 

     // Move the views outside the screen, to the bottom 
     frame.origin.y += self.view.frame.size.height; 

     [view setFrame:frame]; 
    } 
} 

- (void)animateAppearance 
{ 
    NSArray * views = [self animatableViews]; 
    NSUInteger count = [views count]; 

    for (NSUInteger it=0 ; it < count ; ++it) { 

     __weak UIView * weakView = [views objectAtIndex:it]; 
     CGRect referenceFrame = self.view.frame; 

     [UIView animateWithDuration:0.4f 
           delay:0.05f * it 
          options:UIViewAnimationOptionCurveEaseOut 
         animations:^{ 

          CGRect frame = weakView.frame; 
          frame.origin.y -= referenceFrame.size.height; 

          [weakView setFrame:frame]; 
         } 
         completion:^(BOOL finished) { 
         }]; 
    } 
} 

ответ

6

Если вам нужно анимировать что-то, когда представление будет появляться, а потом не трогать подвидов позже, я хотел бы предложить следующее:

  • Не изменять/потрогать viewDidLayoutSubviews
  • Добавить логику для перемещения элементы за пределами экрана (в исходное положение до) в viewWillAppear
  • Добавить логику для анимирования элементов в их правильное положение в viewDidAppear

UPDATE:

Если вы используете автоматическую раскладку (что очень хорошо), вы не можете оживить взгляды, изменяя их кадры непосредственно (потому что автоматическое расположение будет игнорировать это и изменить их снова). Что вам нужно сделать, так это разоблачить выходы для ограничений, ответственных за Y-позицию (в вашем случае), и изменить эти ограничения, а не устанавливать кадры.

Также не забудьте включить вызов [weakView layoutIfNeeded] после обновления ограничений в методе анимации.

+0

Я уже упоминал в вопросе, что я уже пробовал это! Похоже, что в 'viewDidAppear' пользовательский интерфейс еще не готов, и поэтому элементы не перемещаются за пределы экрана. –

+0

Hm. У меня есть ограничения выравнивания центра Y, я не уверен, как оживить это ... –

+0

Но, как ни странно, анимация работает! Должно ли это? –

0

Я делал обе вещи в viewDidAppear:. Похоже, что когда вызывается viewDidAppear:, представление на самом деле не видно, а собирается. Поэтому элементы пользовательского интерфейса никогда не отображаются в исходном положении, если они там заменены.

+0

Подождите, поцарапайте это ... –

+0

Пожалуйста, проверьте все. viewDidAppear называется 'after' view, поэтому все должно быть видимым и уже выведенным. – sha

+0

Да, я заметил. В симуляторе он работал хорошо, но на устройстве он показывает гораздо раньше. Проблема сохраняется. –

Смежные вопросы