Анимация родственных NSViews

Предпосылки и цель

У меня есть окно и три отдельных представления в файле пера в IB. Эти три представления используются для трех «частей» программы: в первом пользователь отбрасывает файл, во втором он выбирает некоторые параметры, а в третьем отображается индикатор выполнения, когда программа выполняет задачу.

Я хочу анимировать эти представления по мере их изменения, и я делаю анимацию постепенного появления / исчезновения. Цель состоит в том, чтобы старый вид (тот, который собирается исчезнуть) исчезнет по мере появления нового вида. Виды имеют разные размеры, поэтому я одновременно анимирую рамку окна (эти представления заполняют окно). Все три представления имеют базовую анимацию, включенную в IB, но ничего больше (например, представление содержимого окна) не имеет.

Код

В начале программы я регистрирую размеры представлений, чтобы использовать их позже, добавляю представления в окно и устанавливаю 2-е и 3-е представление скрытыми.

- (void)awakeFromNib
{
    // Register native views' size (when they get displayed again the window can be set to their bounds)
    view1NativeSize = [firstView bounds].size;
    view2NativeSize = [secondView bounds].size;
    view3NativeSize = [thirdView bounds].size;

    // Add views to the main window's content view
    NSRect viewFrame = [[mainWindow contentView] bounds];
    [firstView setFrame: viewFrame];
    [secondView setFrame: viewFrame];
    [thirdView setFrame: viewFrame];

    [[mainWindow contentView] addSubview: firstView];
    [[mainWindow contentView] addSubview: secondView];
    [[mainWindow contentView] addSubview: thirdView];

    // Set their attributes
    [secondView setHidden: TRUE];
    [thirdView setHidden: TRUE];

    currView = 1;
}

Затем у меня есть три метода переключения между представлениями, где я вычисляю новый оконный фрейм и вызываю метод для анимации.

- (IBAction)goToFirstView: (id)sender
{        
    NSRect newFrame = [mainWindow frame];
    newFrame.size = view1NativeSize;
    newFrame.size.height += [self titleBarHeight]; // Method that returns the title bar height

    if (currView == 1) {
        return;
    }
    else if (currView == 2) {
        [self animateFromView: secondView toView: firstView andWindowFrame: newFrame];
        currView--;
    }
    else if (currView == 3) {
        [self animateFromView: thirdView toView: firstView andWindowFrame: newFrame];
        currView -= 2;
    }
}
- (IBAction)goToSecondView: (id)sender
{
    NSRect newFrame = [mainWindow frame];
    newFrame.size = view2NativeSize;
    newFrame.size.height += [self titleBarHeight];

    if (currView == 2) {
        return;
    }
    else if (currView == 1) {
        [self animateFromView: firstView toView: secondView andWindowFrame: newFrame];
        currView++;
    }
    else if (currView == 3) {        
        [self animateFromView: thirdView toView: secondView andWindowFrame: newFrame];
        currView--;
    }
}
- (IBAction)goToThirdView: (id)sender
{
    NSRect newFrame = [mainWindow frame];
    newFrame.size = view3NativeSize;
    newFrame.size.height += [self titleBarHeight];

    if (currView == 3) {
        return;
    }
    else if (currView == 1) {
        [self animateFromView: firstView toView: thirdView andWindowFrame: newFrame];
        currView += 2;
    }
    else if (currView == 2) {
        [self animateFromView: secondView toView: thirdView andWindowFrame: newFrame];
        currView++;
    }
}

Метод анимации довольно прост. Я оживляю виды.

- (void)animateFromView: (NSView*)oldView
                 toView: (NSView*)newView
         andWindowFrame: (NSRect)newWindowFrame
{
    [NSAnimationContext beginGrouping];
    [[NSAnimationContext currentContext] setDuration: 0.5];

    [[newView animator] setHidden: FALSE];
    [[oldView animator] setHidden: TRUE];
    //[[mainWindow animator] setFrame: newWindowFrame]; --Doesn't work??

    [NSAnimationContext endGrouping];

    [mainWindow setFrame: newWindowFrame display: YES animate: YES];
}

Вопросы

У меня с этим две проблемы (сначала самая важная):

  • На третьем экране есть индикатор прогресса, и он никогда не отображается правильно. Не обновляется! Я вызываю -startAnimation: но она вообще не двигается. Если я отключу CA на этом третьем слое, он не исчезнет / исчезнет правильно, но индикатор выполнения начнет работать (анимировать). Понятия не имею, почему ...

  • В своих многочисленных экспериментах, пытающихся решить первую проблему, я пытался включить CA для представления содержимого окна и выключить CA для трех подпредставлений. Первая проблема не была решена, но я кое-что заметил: таким образом старое представление исчезало по мере того, как исчезало новое представление, тогда как до этого изменения (подпредставления с CA) я мог только замечать исчезновение нового представления. Я записал его и смотрел это в sloooowww-moootion :) и обнаружил, что был прав: старый вид волшебным образом исчезает, и все, что я вижу, это исчезает новый вид. Забавно, я обнаружил, что только после просмотра анимации я действительно хотел. Должен ли я включать CA только для представления содержимого или для всех трех подпредставлений по отдельности? (или эта проблема от чего-то другого?)

Я пробовал много чего, например, включил CA для индикатора выполнения. Я также нашел здесь много вопросов, которые близки к этому, но не касаются конкретно проблемы с индикатором выполнения.

Удачи в поиске решения :)


person Alex    schedule 04.08.2011    source источник


Ответы (1)


Для обработки кроссфейда вы можете просто использовать CATransition, как описано в этот ответ, но для кроссфейда вам не нужно устанавливать тип перехода, поскольку он установлен по умолчанию.

Боюсь, что у меня нет ответа на проблему с индикатором выполнения, возможно, это как-то связано с неортодоксальным способом, которым вы выполняете кроссфейд.

person iain    schedule 05.08.2011
comment
Я пробовал это решение: добавлял только первое представление на -awakeFromNib и заменял его для перехода. Индикатор выполнения по-прежнему не работает, и после некоторых переходов представления начинают отображаться более влево или вниз. Я не знаю, потому что я одновременно меняю оконную раму. В любом случае, я не думаю, что это подойдет ... - person Alex; 05.08.2011