Не так давно я начал свое знакомство с Flex Builder 3. Так как с программированием дружу давно и во всех отношениях, проблем с задачами типа «Привет, мир», сортировкой массива и «как сделать сканирование изображения по кнопке».
Однако я столкнулся с проблемами, которые, несмотря на кажущуюся простоту, не имели простых решений в среде Flex. Для удобства изложения я выделил четыре наиболее интересных из них:
- Добавление множества ресурсов в проект;
- Многоязычное приложение;
- Модальное окно;
- Флекс и 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 #ИТ-компании #ИТ-компании
-
Почему Железо Не Главное
19 Oct, 24 -
Идеальная Производительность Http
19 Oct, 24 -
Raicamp 2015 – День Первый
19 Oct, 24 -
В Стране Закончились Новости
19 Oct, 24 -
А Ты Критикуешь Флэша
19 Oct, 24