Расширенное использование прелоадера во Flash


Любое флеш-приложение разделено на две последовательно выполняемые функциональные части - предзагрузчик (preloader) и основное окно. Предзагрузчик обыкновенно используется для визуализации процесса загрузки - с помощью progress-bar'а демонстрирует, сколько ещё примерно осталось ждать пользователю.

Preloader можно кастомизировать - менять шрифты, цвета, да и вообще весь внешний вид отображения процесса загрузки.Однако, возможности такой кастомизации гораздо шире - в предзагрузчике можно осуществить дополнительное взаимодействие с пользователем, ввод неких пользовательских данных. Например, в прелоадере можно удобно разместить регистрационную форму, форму ввода логина/пароля или регистрационного ключа.

Именно такую возможность я и хочу наглядно показать в этой статье. Для иллюстрации будет использована бесплатная среда разработки FlashDevelop и Flex 3 SDK (для Flex SDK 4 последовательность действий будет та же самая, если не использовать SparkDownloadProgressBar).

Что ж, приступим! Запустите FlashDevelop и создайте новый Flex 3 проект. Можно выбрать AS3 Project with Preloader - но это слишком простой вариант, он нас не устраивает:) Мы создадим предзагрузчик сами, а также учтём некоторые тонкости подключения собственного прелоадера в mxml-разметке.

Создание нового Flex 3 - проекта во FlashDevelop

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

Создание нового класса во FlashDevelop

Базовым классом укажем flash.display.Sprite (нажав на кнопку [Browse...]):

Выбор базового класса во FlashDevelop

Также добавим в список реализуемых интерфейсов mx.preloaders.IPreloaderDisplay:

Добавление реализуемого интерфейса во FlashDevelop

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

Включение кологенерации при создании класса во FlashDevelop

Щелкаем [ОК] - прототип нашего предзагрузчика готов. Чтобы включить его использование в приложении, заполним для mx:Application поле preloader - укажем там имя свежесозданного класса.

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

        protected var _backgroundAlpha:Number = 1;
        public function set backgroundAlpha(value:Number):void
        {
            _backgroundAlpha = value;
        }
        public function get backgroundAlpha():Number
        {
            return _backgroundAlpha;
        }
        
        protected var _stageHeight:Number = 300;
        public function set stageHeight(value:Number):void
        {
            _stageHeight = value;
        }
        public function get stageHeight():Number
        {
            return _stageHeight;
        }
       
        protected var _stageWidth:Number = 400;
        public function set stageWidth(value:Number):void
        {
            _stageWidth = value;
        }
        public function get stageWidth():Number
        {
            return _stageWidth;
        }
       
        protected var _backgroundColor:uint = 0xffffffff;
        public function set backgroundColor(value:uint):void
        {
            _backgroundColor = value;
        }
        public function get backgroundColor():uint
        {
            return _backgroundColor;
        }
       
        protected var _backgroundSize:String = "auto";
        public function set backgroundSize(value:String):void
        {
            _backgroundSize = value;
        }
        public function get backgroundSize():String
        {
            return _backgroundSize;
        }
       
        public function get backgroundImage():Object {return null;}

        public function set backgroundImage (value:Object):void {}

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

Теперь проект соберётся, но дальше предзагрузчика не двинется - необходима обработка событий, возникающих при загрузке приложения. Для этого реализуем сеттер прелоадера-спрайта таким образом:

        protected var _preloaderSprite: Sprite;
        public function set preloader(obj:Sprite):void
        {
            _preloaderSprite = obj;
           
            _preloaderSprite.addEventListener(ProgressEvent.PROGRESS, progressHandler);
            _preloaderSprite.addEventListener(Event.COMPLETE, completeHandler);
            _preloaderSprite.addEventListener(FlexEvent.INIT_PROGRESS, initProgressHandler);
            _preloaderSprite.addEventListener(FlexEvent.INIT_COMPLETE, initCompleteHandler);
        }
       
       protected function progressHandler(event:ProgressEvent): void
        {

        }
       
        protected function completeHandler(event:Event): void
        {
           
        }
       
        protected function initProgressHandler(event:Event): void
        {
           
        }
   
       protected function initCompleteHandler(event:Event): void
        {
            dispatchEvent(new Event(Event.COMPLETE));
        }


При этом следует дополнить секцию импорта:

    import mx.events.FlexEvent;
    import flash.events.Event;
    import flash.events.ProgressEvent;


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

  • progressHandler - вызывается периодически во время процесса загрузки приложения;
  • completeHandler - вызывается единоразово, в момент когда завершена загрузка;
  • initProgressHandler - вызывается периодически в процессе инициализации приложения (если Вы не используете Flex, обрабатывать это событие не нужно);
  • initCompletehandler - вызывается когда и загрузка, и инициализация приложения успешно завершены (если Вы не используете Flex, обрабатывайте вместо этого события completeHandler).

В обработчике последнего события сделаем dispatchEvent - известив таким образом основное приложение о завершении загрузки.

Если собрать и запустить это приложение - оно не "зависнет" на прелоадере как в прошлый раз, а успешно покажет основное окно.

Сделаем ещё шажок вперёд и покажем процент загрузки. Для этого:

1) Добавим импорт import flash.text.TextField;

2) Создадим новое текстовое поле в функции initialize (ага, вот она и пригодилась):
        private var text:TextField;
        public function initialize():void
        {
            text = new TextField;
            addChild(text);
        }

3) В обработчик progressHandler добавим строчку:

        text.text = int(event.bytesLoaded / event.bytesTotal * 100).toString() + "%";

Нужно закомментировать dispatchEvent - чтобы посмотреть на результат, иначе прелоадер "пролетит" очень быстро.

Показ процента загрузки можно сделать сколь угодно красивым и привлекательным, но самое интересное - впереди. А именно - взаимодействие в предзагрузчике с пользователем.

Здесь нас ждёт следующее ограничение - поскольку Flex Framework в прелоадере ещё не загружен, использовать какие-либо элементы управления Flex для этого взаимодействия не получится. Получится использовать - свои собственные, написанные без использования Flex, либо сторонние - с таким же ограничением. MinimalComps (https://github.com/minimalcomps/minimalcomps) вполне подойдут.

После скачивания нужно поместить подкаталоги assets и com в каталог src нашего Preloader-проекта. Сделать это можно с помощью обычного drag'n'drop-а из проводника. Структура проекта теперь будет выглядеть так:

Структура проекта после добавления компонентов MinimalComps

Теперь добавим в наш прелоадер какой-нибудь элемент управления из этой библиотеки, например кнопку. Для этого:

1) Подключим в секции импорта:

        import com.bit101.components.PushButton;   
        import flash.events.MouseEvent;

2) Добавим следующие поля класса:

        private var btn: PushButton;
        private var _buttonPressed:Boolean = false;
        private var _initCompleted:Boolean = false;

3) Тело метода initCompleteHandler - сделаем таким:       

            _initCompleted = true;
            if (_buttonPressed)
            {
                dispatchEvent(new Event(Event.COMPLETE));
            }

4) В initialize() допишем:

            btn = new PushButton(this);
            btn.label = "OK";
            btn.height = 24;
            btn.width = 32;
            btn.y = (stageHeight - btn.height) / 2;
            btn.x = (stageWidth - btn.width) / 2 ;
            btn.addEventListener(MouseEvent.CLICK, OKButtonClick);
            addChild(btn);

5) И, наконец, добавим обработчик щелчка по кнопке:

        private function OKButtonClick(event: MouseEvent):void
        {
            _buttonPressed = true;
            if (_initCompleted)
            {
                dispatchEvent(new Event(Event.COMPLETE));
            }
        }


ВАЖНО: при использовании третьего Flex Framework (в нашем случае) придётся раскомментировать строчку
 [Embed(source="/assets/pf_ronda_seven.ttf", fontName="PF Ronda Seven", mimeType="application/x-font")]
и закомментировать
[Embed(source="/assets/pf_ronda_seven.ttf", embedAsCFF="false", fontName="PF Ronda Seven", mimeType="application/x-font")]

в файле com / bit101 / components / Component.as

После сборки и запуска приложения прелоадер передаст управление только после щелчка по кнопке [OK]:

Ожидание нажатия кнопки пользователем во Flash preloader

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

Форма для вода логина и пароля в прелоадере Flash

29 января 2012 02:59 — Георгий Чурочкин