Первые, Но Трудные Шаги Во Flex

Не так давно я начал свое знакомство с Flex Builder 3. Так как с программированием дружу давно и во всех отношениях, проблем с задачами типа «Привет, мир», сортировкой массива и «как сделать сканирование изображения по кнопке».

Однако я столкнулся с проблемами, которые, несмотря на кажущуюся простоту, не имели простых решений в среде Flex. Для удобства изложения я выделил четыре наиболее интересных из них:

  1. Добавление множества ресурсов в проект;
  2. Многоязычное приложение;
  3. Модальное окно;
  4. Флекс и CSS.
Задания расположены в порядке убывания сложности.

Буду рад, если кто-то решил эти же проблемы проще (или иначе, чем я) и описал эти решения в комментариях.



1. Добавление нескольких ресурсов в проект

Я быстро обнаружил, что в проект Flex легко встроить файл любого типа:

[Embed(source="index.xml", mimeType="application/octet-stream")] private static var index_xml : Class; [Embed(source="picture.png")] private static var picture_png : Class;

Таким образом, во время работы приложения мы можем получить к ним доступ, просто создав необходимый объект, а не загружая файл из сети или с локального диска.

Однако почти сразу столкнулся с ошибкой: 1067 Неявное приведение типа int к неподходящему классу.

Следующий код выдал эту ошибку:

public class res { [Embed(source="test.png")] public static var test: Class; public static var res_test: int; }

Как выяснилось, Flex генерирует промежуточные классы AS для встроенных ресурсов.

Для примера выше был создан класс:

public class res_test extends mx.core.BitmapAsset { public function res_test() { super(); } }

В этом мне помогла полезная директива компилятора: сохранить-сгенерированный-actionscript .

Если для этой директивы установлено значение истинный , компилятор для всех промежуточных сгенерированных классов создает файлы в папке исходный/сгенерированный/ .

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

Ни помощь, ни книги, ни форумы не дали ответа.

Честно говоря, я до сих пор не понимаю: либо никто этого не делал, либо все делали, но молчали.

Поскольку строки типа [Встроить(источник="папка\")] Флекс упорно отказывался, я решил пойти на хитрость: заархивировать папку ресурса.

Таким образом я получаю файл, который могу включить в проект, как и любой другой.

Дело за библиотекой классов по работе с архивами.

Найти такие библиотеки не составило труда.

Например, ZIP-библиотека AS3 или FZip .

Теперь я мог использовать любой файл из архива во время работы приложения.

И я мог без всяких усилий поместить в архив столько файлов, сколько хотел.

Кажется, все так, как должно быть.

Но нет. Файлы из архива возвращаются в виде ByteArray. Если это текстовые файлы или двоичные данные, то нет проблем.

А вот если это образ или, не дай бог, swf, то начинаются танцы с бубном.

Просто преобразовать ByteArray в BitmapData или BitmapAsset оказалось невозможно.

Не было даже конвертеров для различных типов данных: png, jpeg, swf и т. д. Во Flex есть PNGEncoder, JPEGEncoder и так далее, но почему-то нет PNGDecoder, JPEGDecoder. Еще немного просмотрев справку, я нашел класс Loader. В этом классе есть метод loadBytes(), который принимает ByteArray в качестве параметра, автоматически распознает содержимое и преобразует его в нужный класс Flex. Смирившись с необходимостью подписаться на событие завершения загрузки и как-то выдрать свои данные из этого компонента, я ожидал, что за меня это «сделают красиво».

Не так.

Тестируя эту опцию в среде Flex, я не заметил никаких проблем.

Однако, когда я выпустил релиз и запустил его, я получил ошибку.

Суть ее сводилась к следующему: у меня нет прав на доступ к файлу "MyApplicationFile.swf.<<1> > .

byteArray()" .

Другими словами, у меня нет разрешения на доступ к моему массиву.

Вот что меня шокировало.

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

, или не подпадает под какое-либо другое правило безопасности проигрывателя Flash. Но я не понимаю, почему мой массив, который я только что создал и инициализировал сам, оказался каким-то локальным ресурсом, к которому я тоже не могу получить доступ через Loader! Придя в себя, я решил бороться дальше.

Следующей идеей было создать некую надстройку для Flex, которая при компиляции преобразовывала бы строки типа [Встроить(источник="папка\")] в класс AS3, где все файлы из этой папки будут явно указаны со встроенным флагом.

Мне было лень писать плагин, а макросов во Flex я не нашел.

Поэтому я обратился к другу, который пишет Java в Eclipse. Я рассудил, что, поскольку Flex основан на Eclipse, возможно, решения для Eclipse подойдут и для Flex. Немного подумав, друг посоветовал мне Апач Муравей .

Для разработчиков Java он заменяет make. При этом он может делать невообразимые вещи с файлами, папками, запускать приложения, редактировать текстовые файлы и многое другое.

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

Поэтому я отказался от идеи использования Apache Ant и мне остался только один способ (который я мог придумать) добиться желаемого.

И этот путь заключался в создании небольшого приложения, которое генерировало бы файл AS3 для заданной папки.

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

За двадцать минут я написал на C++ программу, которая генерирует этот файл AS3. Остаётся единственная проблема — не забыть запустить эту программу при изменении ресурсов в папке :).

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

Я все еще надеюсь, что кто-нибудь покажет мне лучшее решение проблемы включения нескольких ресурсов в проект.

2. Многоязычное приложение

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

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

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

Класс создан:

public class LanguageProvider { private var fobj_languageData: Array = new Array(); public function Clear(): void { fobj_languageData = new Array(); } public function AddLanguageData(fileName : String): void { var id : String = ""; var parent : XML = null; for each (var item: XML in ResourcesManager.FileAsXML(fileName).

*.

(hasOwnProperty("@value"))) { id = item.name(); parent = item.parent(); while (parent != null) { id = parent.name() + ".

" + id; parent = parent.parent(); } fobj_languageData[id] = item.@value; } } public function GetStringFor(item : String): String { var result: String = fobj_languageData[item]; if (result != null) return result; else return "<-!->"; } }

Также был создан файл локализации: Почему это лучше стандартного метода:

  • Используются файлы XML, а не ini. Это позволяет структурировать языковые данные;
  • Доступ к строке локализации выглядит примерно так: меню.

    настройки.

    звук.

    Сразу понятно, что речь идет о звуке в меню настроек;

  • Этот метод позволяет более детально контролировать процесс локализации - задавать строку по умолчанию для неопределенных строк локализации, генерировать или не генерировать исключения, оптимизировать процесс заполнения массива локализации и т.д.
Чем это хуже стандартного метода:
  • Вам нужно делать все вручную: включать файлы локализации, загружать их, назначать компонентам строки и т. д.
Я не претендую на истину в последней инстанции, но лично мне мой подход более удобен.

Возможно, это будет полезно кому-то еще.



3. Модальное окно

Возникла необходимость создать свое модальное «окно».

Аналогично окну оповещений.

Я взял слово «окно» в кавычки, потому что на самом деле это просто панели, а не окна как таковые.

Я, конечно, залез в исходный код класса Alert и вытащил оттуда всё, что мне нужно.



<Эxml version="1.0" encoding="utf-8"?> < mx:Panel xmlns:mx="http://www.adobe.com/2006/mxml " layout="absolute" width="400" height="300"> <mx:Script> <![CDATA[ import mx.managers.PopUpManager; import mx.events.CloseEvent; import mx.core.Application; // private private var fbol_init: Boolean = false; private var fobj_closeHandler: Function = null; // protected override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void { super.updateDisplayList(unscaledWidth, unscaledHeight); if (!fbol_init) { var x:Number; var y:Number; if (parent == systemManager) { x = (screen.width - width) / 2; y = (screen.height - height) / 2; } else if (parent != null) { x = (parent.width - width) / 2; y = (parent.height - height) / 2; } else { x = (Application.application.width - width) / 2; y = (Application.application.height - height) / 2; } // Set my position, because my parent won't do it for me. move(Math.round(x), Math.round(y)); fbol_init = true; } } // public public virtual function Show(closeHandler:Function = null): void { fobj_closeHandler = closeHandler; if (closeHandler != null) this.addEventListener(CloseEvent.CLOSE, closeHandler); PopUpManager.addPopUp(this, Sprite(Application.application), true); } public virtual function Close(): void { PopUpManager.removePopUp(this); fbol_shown = false; dispatchEvent(new CloseEvent(CloseEvent.CLOSE)); if (fobj_closeHandler != null) removeEventListener(CloseEvent.CLOSE, fobj_closeHandler); } ]]> </mx:Script> </mx:Panel>

Все очень просто, но надеюсь кому-то будет полезно :).



4. Flex и CSS

Ни для кого не секрет, что Flex и CSS дружат. И они очень близкие друзья.

Вы можете установить CSS для всего приложения и определить в нем, как будут выглядеть кнопки, панели и т. д. С другой стороны, есть компонент TextArea. Этот компонент имеет свойства htmlText и styleSheet. Таким образом, вы можете поместить HTML-текст в этот компонент, и он будет отображаться с использованием стиля, указанного в таблице стилей.

Теперь вопрос: как мне установить CSS для всех TextArea в приложении, с помощью которого внутри них должен отображаться htmlText? Если мы зададим CSS для всего приложения и укажем в нем, как будет выглядеть TextArea, то текст в этом компоненте будет выглядеть именно так.

Если мы описываем какие-то классы, которые используются в HTML-тексте в TextArea, то эти стили никак не применяются.

Что несколько усложняет все это, так это то, что свойство styleSheet TextArea доступно только из AS3 и не имеет аналога в MXML. Не найдя стандартного решения, я придумал своё — создал наследника TextArea:

<Эxml version="1.0" encoding="utf-8"?> < mx:TextArea xmlns:mx="http://www.adobe.com/2006/mxml " width="100" height="100" creationComplete="OnCreationComplete()" borderThickness="0" editable="false" horizontalScrollPolicy="off" verticalScrollPolicy="off"> <mx:Script> <![CDATA[ // static private static var fobj_styleSheet : StyleSheet = null; public static function SetStyleSheet(ss : StyleSheet):void { fobj_styleSheet = ss; } // private private function OnCreationComplete(): void { if (fobj_styleSheet != null) this.styleSheet = fobj_styleSheet; } ]]> </mx:Script> </mx:TextArea>

Как вы можете видеть из кода, я определил статическое поле и метод в своем преемнике.

Теперь в приложениях использую не TextArea, а ее наследника.

Где-то в коде приложения я один раз загружаю объект CSS и передаю его статической функции SetStyleSheet. Получается, что все объекты этого класса при создании теперь добросовестно пишут свой собственный CSS. Надеюсь, мой опыт будет кому-то полезен.

Заранее благодарю за комментарии и дополнения :).

Теги: #flex 3 #первые шаги #встроенный #многоязычие #CSS #ИТ-компании #ИТ-компании

Вместе с данным постом часто просматривают:

Автор Статьи


Зарегистрирован: 2019-12-10 15:07:06
Баллов опыта: 0
Всего постов на сайте: 0
Всего комментарий на сайте: 0
Dima Manisha

Dima Manisha

Эксперт Wmlog. Профессиональный веб-мастер, SEO-специалист, дизайнер, маркетолог и интернет-предприниматель.