» » Что общего между конечными автоматами, анимацией и Xamarin.Forms

 

Что общего между конечными автоматами, анимацией и Xamarin.Forms

Автор: admin от 11-08-2017, 17:10, посмотрело: 29

Если вы были студентом технической специальности, то наверняка помните курс, посвященный конечным автоматам. Эта простая, но очень емкая модель (конечный автомат, он же finite state machine, он же FSM) используется довольно широко, хотя и большинство программистов о ней незаслуженно забывают. Сегодня мы поговорим о конечных автоматах и их применении в создании комплексных анимаций в приложениях на Xamarin.Forms.



Что общего между конечными автоматами, анимацией и Xamarin.Forms


Анимации в Xamarin.Forms



Если вы уже используете Xamarin.Forms в реальных проектах, то наверняка сталкивались со встроенным механизмом анимаций. Если нет, то рекомендуем начать знакомство со статей «Creating Animations with Xamarin.Forms» и «Compound Animations».



Чаще всего требуется анимировать следующие свойства:




  • Scale, масштаб элемента;

  • Opacity, прозрачность;

  • Translation, дополнительное смещение по x, y, относительно полученного при компоновке положения;

  • Rotation, вращение вокруг осей x, y, z.



В Xamarin.Forms для задания обозначенных свойств используются механизмы ОС низкого уровня, что отлично сказывается на производительности — нет проблем анимировать сразу целую кучу объектов. В нашем примере мы остановимся именно на этих свойствах, но при желании вы сможете самостоятельно расширить описанные ниже механизмы.



Конечные автоматы



Если описать конечный автомат человеческим языком, то это некий объект, который может находится в различных устойчивых состояниях (например, “загрузка” или “ошибка”). Свои состояния автомат меняет под воздействием внешних событий. Количество состояний конечно. Примерами таких автоматов являются лифты и светофоры.





Что общего между конечными автоматами, анимацией и Xamarin.Forms


Если вы по какой-то причине не учились в институте на технической специальности или не изучали теорию, то рекомендуем начать знакомство с этой статьи.



Какое это все имеет отношение к анимациям и тем более к Xamarin.Forms? Давайте посмотрим.



Один экран, много состояний, есть анимации перехода



В статье «Работаем с состояниями экранов в Xamarin.Forms» мы уже описывали компонент StateContainer, упрощающий разработку сложных интерфейсов и подходящий для большинства экранов в бизнес-приложениях. Этот компонент хорошо работает, когда у нас все состояния существуют независимо друг от друга и между ними достаточно простого перехода «один исчез — второй появился».



Что общего между конечными автоматами, анимацией и Xamarin.Forms


Но что делать, если необходимо реализовать комплексный и анимированный переход из одного состояния в другое? Чтобы выезжало, вращалось и прыгало.



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



Представим, что у нас анимированные переходы между следующими состояниями ОДНОГО экрана:



Что общего между конечными автоматами, анимацией и Xamarin.Forms

Как видим, у нас получается такой конечный автомат:



Что общего между конечными автоматами, анимацией и Xamarin.Forms

Необходимо реализовать следующие анимации при переходе из состояния в состояние:




  • При входе в FindAddress нужно скрыть с анимацией старый контент и плавно показать новый. Плюс для пикантности будем анимировать кнопки во время появления;

  • При переходе в ShowRoute необходимо скрыть старое состояние, а снизу экрана должна выехать табличка с информацией о маршруте;

  • При переходе в Drive необходимо скрыть старое состояние и сверху должна выехать табличка с информацией о маршруте;

  • При переходе в Main (кроме первого запуска) необходимо скрыть текущее состояние и плавно отобразить кнопку, добавим к ней также небольшую анимацию изменения масштаба.





Пишем свой автомат



Мы возьмем самую простую реализацию:




  • У автомата есть фиксированный набор состояний, которые задаются при инициализации;

  • Каждое из состояний описывается набором необходимых анимаций (конечные значения properties) для элементов UI;

  • При входе в новое состояние параллельно запускаются все анимации из массива, добавленного при инициализации автомата.



Никакую историю переходов хранить не будем, также не важно по какому пользовательскому событию автомат перешел из одного состояния в другое. Есть только переход в новое состояние, который сопровождается анимациями.



Итак, простейший автомат, который мы назовем Storyboard, будет выглядеть следующим образом:



public enum AnimationType {
    Scale,
    Opacity,
    TranslationX,
    TranslationY,
    Rotation
}

public class Storyboard {
    readonly Dictionary<string, ViewTransition[]> _stateTransitions = new Dictionary<string, ViewTransition[]>();

    public void Add(object state, ViewTransition[] viewTransitions) {
        var stateStr = state?.ToString().ToUpperInvariant();
        _stateTransitions.Add(stateStr, viewTransitions);
    }

    public void Go(object newState, bool withAnimation = true) {
        var newStateStr = newState?.ToString().ToUpperInvariant();
        
        // Get all ViewTransitions 
        var viewTransitions = _stateTransitions[newStateStr];
        
        // Get transition tasks
        var tasks = viewTransitions.Select(viewTransition => viewTransition.GetTransition(withAnimation));
        
        // Run all transition tasks
        Task.WhenAll(tasks);
    }
}

public class ViewTransition {
        // Skipped. See complete sample in repository below
        
    public async Task GetTransition(bool withAnimation) {
        VisualElement targetElement;
        if( !_targetElementReference.TryGetTarget(out targetElement) )
           throw new ObjectDisposedException("Target VisualElement was disposed");
        
        if( _delay > 0 ) await Task.Delay(_delay);
        
        withAnimation &= _length > 0;
        
        switch ( _animationType ) {
            case AnimationType.Scale:
                if( withAnimation )
                   await targetElement.ScaleTo(_endValue, _length, _easing);
                else
                   targetElement.Scale = _endValue;
                break;
                
                // See complete sample in repository below
            default:
                throw new ArgumentOutOfRangeException();
        }
    }
}


В примере выше опущены проверки входных данных, полную версию можете найти в репозитории (ссылка в конце статьи).



Как видим, при переходе в новое состояние просто в параллели происходят плавные изменения необходимых свойств. Есть также возможность перейти в новое состояние без анимации.



Используем конечный автомат



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



_storyboard.Add(States.Drive, new[] {
   new ViewTransition(ShowRouteView, AnimationType.TranslationY, 200),
   new ViewTransition(ShowRouteView, AnimationType.Opacity, 0, 0, delay: 250),
   new ViewTransition(DriveView, AnimationType.TranslationY, 0, 300, delay: 250), // Active and visible
   new ViewTransition(DriveView, AnimationType.Opacity, 1, 0) // Active and visible
});


Как видим, для состояния Drive мы задали массив индивидуальных анимаций. ShowRouteView и DriveView — обычные View, заданные в XAML, пример ниже.



А вот для перехода в новое состояние достаточно простоы вызвать метод Go():



_storyboard.Go(States.ShowRoute);


Кода получается относительно немного и групповые анимации создаются по факту просто набором чисел. Работать наш конечный автомат может не только со страницами, но и с отдельными View, что расширяет варианты его применения. Использовать Storyboard лучше внутри кода страницы (Page), не перемешивая его с бизнес-логикой.



Также приведем пример XAML, в котором описаны все элементы пользовательского интерфейса.



Что общего между конечными автоматами, анимацией и Xamarin.Forms


Если вы решите добавить возможность смены цвета элементов с помощью анимаций, то рекомендуем познакомиться с реализацией, описанной в статье «Building Custom Animations in Xamarin.Forms».



Полный код проекта из статьи вы можете найти в нашем репозитории:

https://bitbucket.org/binwell/statemachine.



И как всегда, задавайте ваши вопросы в комментариях. До связи!



Об авторе



Что общего между конечными автоматами, анимацией и Xamarin.Forms Вячеслав Черников — руководитель отдела разработки компании Binwell, Microsoft MVP и Xamarin Certified Developer. В прошлом — один из Nokia Champion и Qt Certified Specialist, в настоящее время — специалист по платформам Xamarin и Azure. В сферу mobile пришел в 2005 году, с 2008 года занимается разработкой мобильных приложений: начинал с Symbian, Maemo, Meego, Windows Mobile, потом перешел на iOS, Android и Windows Phone. Статьи Вячеслава вы также можете прочитать в блоге на Medium.



Другие статьи автора:





Источник: Хабрахабр

Категория: Программирование, Веб-разработка, Microsoft

Уважаемый посетитель, Вы зашли на сайт как незарегистрированный пользователь.
Мы рекомендуем Вам зарегистрироваться либо войти на сайт под своим именем.

Добавление комментария

Имя:*
E-Mail:
Комментарий:
Полужирный Наклонный текст Подчеркнутый текст Зачеркнутый текст | Выравнивание по левому краю По центру Выравнивание по правому краю | Вставка смайликов Выбор цвета | Скрытый текст Вставка цитаты Преобразовать выбранный текст из транслитерации в кириллицу Вставка спойлера
Введите два слова, показанных на изображении: *