| « Другой подход к стилизации Flex-приложения | Отображение произвольного HTML силами TLF » |
Runtime иконки для Flex-компонент
Проблема
Flex SDK позволяет в качестве значение стиля “icon” для mx.controls.Button и других icon-стилей других компонент указывать только Class, экземпляры которого будут удовлетворять IFlexDisplayObject. Обычно это делается так:
- [Embed("mouse.png")]
- private var icon1:Class;
- <mx:Button icon="{icon1}"/>
Проблема в том, что mouse.png может определяться в процессе работы приложения.
Возможные пути решения
По мере поступления картинок компилировать из них SWF и подгружать.
Данный метод не всегда доступен и не удобен.
Сделать monkey-patch соответсвующих компонент SDK.
При смене версии Flex SDK возможно придется изменять и патчи. Также monkey patching приносит проблемы при работе с RSL. (eng)
Сгенерировать SWF с картинкой на лету.
Для этого придется изучить SWF Specification и AVM2 Bytecode.
Я разбирал уже скомпилированную SWF с одной картинкой, дошел до байткода. В случае PNG с прозрачностью выяснилось, что маска прозрачности, похоже, хранится отдельно, а сама картинка хранится в байткоде, так что не ждите легкого решения. По дороге выяснилось, что минимальный размер SWF - где-то 30 байтов.
Использовать несколько заранее вкомпилированных классов и ассоциировать с ними BitmapData по мере необходимости.
Этот способ будет рассмотрен далее.
Кеш классов-наследников BitmapAsset
Класс-картинка должен просто вызвать родительский конструктор BitmapAsset, передав ему нужное значение BitmapData. Реазилуем это следующим образом:
- package bitmaps
- {
- import flash.display.BitmapData;
- import flash.display.PixelSnapping;
- import flash.utils.getQualifiedClassName;
- import mx.core.BitmapAsset;
- public class RuntimeBitmapAsset extends BitmapAsset
- {
- /**
- * Maps class names to BitmapData instances.
- */
- public static const bitmapDatas:Object = {};
- public function RuntimeBitmapAsset()
- {
- var name:String = getQualifiedClassName(this);
- var bitmapData:BitmapData = bitmapDatas[name];
- if (!bitmapData)
- trace("Warning: BitmapData for \"" + name + "\" not found");
- super(bitmapData, PixelSnapping.AUTO, true);
- }
- }
- }
Далее создаем нужное количество классов-приспособленцев B0, B1, B2 …:
- package bitmaps
- {
- public class B0 extends RuntimeBitmapAsset
- {
- }
- }
Использование
- import flash.utils.getQualifiedClassName;
- import bitmaps.*;
- import mx.controls.Button;
- /**
- * Array of Class-es.
- */
- private var bitmapClasses:Array = [ B0, B1, B2 ];
- /**
- * Index of next available element in bitmapClasses
- */
- private var index:int = 0;
- private function addSample():void
- {
- if (container.numChildren == bitmapClasses.length)
- container.removeChildAt(0);
- var button:Button = new Button();
- button.label = "Button with icon using cache class B" + index;
- var theClass:Class = getNextBitmapClass(getRandomBitmapData());
- button.setStyle("icon", theClass);
- container.addChild(button);
- }
- private function getNextBitmapClass(bitmapData:BitmapData):Class
- {
- var bitmapClass:Class = bitmapClasses[index];
- index = (index + 1) % bitmapClasses.length;
- RuntimeBitmapAsset.bitmapDatas[getQualifiedClassName(new bitmapClass())] = bitmapData;
- return bitmapClass;
- }
- private function getRandomBitmapData():BitmapData
- {
- var bitmapData:BitmapData = new BitmapData(16, 16, true, 0);
- var seed:Number = Math.floor(Math.random() * 10);
- var channels:uint = BitmapDataChannel.RED | BitmapDataChannel.BLUE;
- bitmapData.perlinNoise(100 * Math.random(), 100 * Math.random(), 10 * Math.random(),
- seed, false, true, channels, false, null);
- return bitmapData;
- }
Трекбек адрес этой записи
URL трекбека (щелкните правой кнопкой мыши и скопируйте ссылку)

подрочил, спасибо





