Анимация братьев и сестер NSViews - PullRequest
2 голосов
/ 04 августа 2011

Справочная информация и цель

У меня есть окно и три отдельных вида в файле пера в 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 для индикатора выполнения. Я также нашел здесь много вопросов, которые близки к этому, но не решают проблему с индикатором выполнения.

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

1 Ответ

0 голосов
/ 05 августа 2011

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

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

...