IconItemRenderer with HTML Support - html

Im currently developing an custom Icon Item Renderer that support HTML in the message fields.
I have two files.
view1.mxml - that contains the spak list component
htmlRenderer.mxml - the icon item renderer
Codes
htmlRenderer.mxml
<?xml version="1.0" encoding="utf-8"?>
<s:ItemRenderer
xmlns:fx = "http://ns.adobe.com/mxml/2009"
xmlns:s = "library://ns.adobe.com/flex/spark"
xmlns:mx = "library://ns.adobe.com/flex/mx"
autoDrawBackground = "true"
width = "100%"
creationComplete="callLater(renderHtml, ['test'])">
<fx:Script>
<![CDATA[
import flash.display.Shape;
import mx.core.FlexGlobals;
import mx.core.UIComponent;
import mx.events.FlexEvent;
import spark.components.*;
import spark.components.supportClasses.StyleableTextField;
import spark.primitives.Rect;
public var mainWrapper:VGroup = new VGroup();
public var mainContainer:HGroup = new HGroup();
//Icon Item Renderer
public var iconItemWrapper:HGroup = new HGroup();
public var iconItemImage:Image = new Image();
/* Text elements */
public var iconItemTextGroup:VGroup = new VGroup();
public var iconItemLabel:Label = new Label();
public var iconItemHtmlMessagex:TextArea = new TextArea();
/* Star rating */
public var iconItemRaterGroup:HGroup = new HGroup();
public var iconItemRater:*;
//Decorator
public var decoratorGroup:VGroup = new VGroup();
public var decoratorText:Label = new Label();
public var counterGroup:Rect = new Rect();
public var counterText:Label = new Label();
public var decoratorImage:Image = new Image();
//Icon Item Borders
public var iconItemTopBorder:Rect = new Rect();
public var iconItemBottomBorder:Rect = new Rect();
public var iconItemBackground:Rect = new Rect();
import flash.display.Graphics;
import mx.graphics.LinearGradient;
import mx.graphics.GradientEntry;
protected function drawHeader():void
{
decoratorText.setStyle("fontFamily","Roboto");
decoratorText.setStyle("fontSize","16");
decoratorText.setStyle("fontWeight","bold");
decoratorText.setStyle("color","#ffffff");
decoratorText.setStyle("paddingRight","5");
decoratorText.setStyle("paddingTop","5");
decoratorText.setStyle("paddingLeft","5");
decoratorText.setStyle("paddingBottom","5");
decoratorText.text = data.Location
addElement(decoratorText);
}
protected function renderIconItem():void
{
//main wrapper
iconItemWrapper.paddingBottom=5;
iconItemWrapper.paddingTop=5;
iconItemWrapper.paddingLeft=5;
iconItemWrapper.verticalAlign="top";
addElement(iconItemWrapper);
//icon
iconItemImage.source = data.Image;
if(iconItemImage.sourceWidth > 64){
iconItemImage.width = 64;
iconItemImage.height = 64;
}else{
iconItemImage.width = iconItemImage.sourceWidth;
iconItemImage.height = iconItemImage.sourceHeight;
}
iconItemImage.sourceWidth
iconItemWrapper.addElement(iconItemImage);
iconItemTextGroup.gap = 0;
iconItemTextGroup.paddingBottom=0;
iconItemTextGroup.paddingTop=0;
iconItemTextGroup.verticalAlign="top";
iconItemWrapper.addElement(iconItemTextGroup);
//title
iconItemLabel.setStyle("fontFamily","Roboto");
iconItemLabel.setStyle("fontWeight","bold");
iconItemLabel.setStyle("color","#000000");
iconItemLabel.setStyle("fontSize","16");
iconItemLabel.setStyle("paddingRight","0");
iconItemLabel.setStyle("paddingTop","0");
iconItemLabel.setStyle("paddingLeft","0");
iconItemLabel.setStyle("paddingBottom","0");
iconItemLabel.text = data.Product;
iconItemTextGroup.addElement(iconItemLabel);
//message
iconItemHtmlMessagex.focusEnabled = false;
iconItemHtmlMessagex.selectable = false;
iconItemHtmlMessagex.setStyle("paddingLeft","0");
iconItemHtmlMessagex.setStyle("paddingTop","0");
iconItemHtmlMessagex.setStyle("borderVisible","false");
iconItemHtmlMessagex.setStyle("contentBackgroundAlpha","0");
iconItemTextGroup.addElement(iconItemHtmlMessagex);
renderMessageText();
//iconItemRaterGroup
//iconItemRaterGroup.paddingTop=0;
//iconItemRaterGroup.verticalAlign="bottom";
//iconItemTextGroup.addElement(iconItemRaterGroup);
//decoratorGroup
decoratorGroup.paddingTop=10;
decoratorGroup.verticalAlign="bottom";
iconItemWrapper.addElement(decoratorGroup);
//decoratorText
decoratorText.setStyle("fontFamily","Roboto");
decoratorText.setStyle("fontSize","12");
decoratorText.setStyle("fontWeight","bold");
decoratorText.setStyle("color","#777777");
decoratorText.setStyle("paddingRight","0");
decoratorText.setStyle("paddingTop","0");
decoratorText.setStyle("paddingLeft","0");
decoratorText.setStyle("paddingBottom","0");
decoratorText.text = data.Location
decoratorGroup.addElement(decoratorText);
//decoratorImage
decoratorImage.width = 32;
decoratorImage.height = 32;
decoratorImage.source = "recycle-icon.png";
decoratorImage.sourceHeight
decoratorImage.sourceWidth
decoratorGroup.addElement(decoratorImage);
}
public var myStyleSheet:StyleSheet = new StyleSheet();
private function renderMessageText():void {
var styles:String = "p{ font-size: 11px; }
a{ font-size: 11px; color: #0C81F5; text-decoration: underline; }
a:hover { color: #CCDEF0; text-decoration: underline; }";
myStyleSheet.parseCSS(styles);
StyleableTextField(iconItemHtmlMessagex.textDisplay).htmlText = data.Description2;
}
public function renderHtml(varx:String):void{
setTimeout(renderHtmlTimeout, 1);
}
public function renderHtmlTimeout():void{
StyleableTextField(iconItemHtmlMessagex.textDisplay).styleSheet = myStyleSheet;
}
override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void
{
super.updateDisplayList(unscaledWidth, unscaledHeight);
renderIconItem();
this.graphics.clear();
this.graphics.beginGradientFill(GradientType.LINEAR, [0xffffff,0xefefef], [1,1], [0,255],verticalGradientMatrix(0,0,unscaledWidth, unscaledHeight));
this.graphics.drawRect(0,0,unscaledWidth, unscaledHeight);
}
]]>
</fx:Script>
</s:ItemRenderer>
and view1.mxml
<?xml version="1.0" encoding="utf-8"?>
<s:View xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
creationComplete="ini();">
<fx:Declarations>
<s:HTTPService id="xmlDataResource" url="properties.xml"
result="xmlDatasource = xmlDataResource.lastResult.slist.products"/>
</fx:Declarations>
<fx:Script>
<![CDATA[
import mx.collections.ArrayCollection;
[Bindable]
public var xmlDatasource:ArrayCollection;
public function ini():void{
xmlDataResource.send();
}
]]>
</fx:Script>
<s:List id="categoryList" left="0" right="0" top="0" bottom="0" borderAlpha="0.5"
itemRenderer="htmlRenderer"
dataProvider="{xmlDatasource}">
</s:List>
</s:View>
The problem is that when the list loads data, only list items in the view port are rendered and the rest of the information is hidden.
Any help as im in the verge of getting a breakthrough in flex mobile.
below is the screen shot
thank

Basically, the rest is not hidden, it is simply not there :)
The concept of the List-based classes/components in Flex is, the only the visible data is assigned and rendered. If e.g. your list has the height to display 8 items, then it will create 10 items and reuse them. If you scroll up and an items leaves the viewport, it is placed at the bottom of the list and gets new data.
If you want to create all objects and scroll them, try wrapping a VGroup inside a Scroller.

Related

Can't get animation in Custom layout to work

I'd like to create a layout that I can animate my items in. So when a dataprovider gets set on my List, the List's layout will then animate those items onto the screen.
So I've created a CustomLayout and added an update() function.
In the updateDisplayList the items are traced out just fine.
But in the update() function where I want to do the animation, the items are tracing out as null even though if I trace layoutTarget's numElement's I get four! If I use a setTimeout after setting the _dataProvider in my Main app of a second or two, then call update() in the ListLayout, then the traces work fine. So my question is, how can I ensure that I call update() to animate the items in when they are actually available??
Main app:
<?xml version="1.0" encoding="utf-8"?>
<s:WindowedApplication xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx"
xmlns:custom="*"
creationComplete="handleCreationComplete()">
<fx:Declarations>
<!-- Place non-visual elements (e.g., services, value objects) here -->
</fx:Declarations>
<fx:Script>
<![CDATA[
import mx.collections.ArrayCollection;
[Bindable]
private var _dataProvider:ArrayCollection;
public function set dataProvider(value:ArrayCollection):void
{
_dataProvider = value;
listLayout.update();
}
private function handleCreationComplete():void
{
var arr:Array = new Array( { label:"1" }, { label:"2" }, { label:"3" }, { label:"4" } );
dataProvider = new ArrayCollection(arr);
}
]]>
</fx:Script>
<s:List id="list"
dataProvider="{ _dataProvider }"
labelField="label">
<s:layout>
<custom:ListLayout id="listLayout" />
</s:layout>
</s:List>
</s:WindowedApplication>
ListLayout:
package
{
import mx.core.ILayoutElement;
import spark.components.supportClasses.GroupBase;
import spark.layouts.supportClasses.LayoutBase;
/**
* ...
* #author
*/
public class ListLayout extends LayoutBase
{
public function update():void
{
var layoutTarget:GroupBase = target;
//layoutTarget.autoLayout = false;
var count:int = layoutTarget.numElements;
trace(count); //traces 4
for (var i:int = 0; i < count; i++)
{
var item:ILayoutElement = useVirtualLayout ? layoutTarget.getVirtualElementAt(i) : layoutTarget.getElementAt(i);
trace(item); //traces null
}
}
override public function updateDisplayList(width:Number, height:Number):void
{
super.updateDisplayList(width, height);
var layoutTarget:GroupBase = target;
var count:int = layoutTarget.numElements;
for (var i:int = 0; i < count; i++)
{
var item:ILayoutElement = useVirtualLayout ? layoutTarget.getVirtualElementAt(i) : layoutTarget.getElementAt(i);
trace(item); //traces out the item
}
}
}
}
Before you call update on your listLayout, you need to validate your "list" to make sure all the elements are available. So add one line list.validateNow() in set dataProvider function as below:
public function set dataProvider(value:ArrayCollection):void
{
_dataProvider = value;
list.validateNow();
listLayout.update();
}

spark Combobox selection is not visible if list changes

I am using a Spark Combobox and a filter function to filter characters in the firstName and lastName. When user types "a" the drop down list is showing all the filtered items with selecting "aram,babu" in the drop down and also showing text as "aram,babu" in the textinput. If the user presses "r", the text input displays "aram,babu", but the drop down list selection disappears. Hitting Enter or clicking the mouse outside the drop down results in the wrong item (last item, i.e. "armu,babu") being selected.
<?xml version="1.0"?>
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx" xmlns:local="*">
<fx:Script><![CDATA[
import mx.collections.ArrayCollection;
private function labelField(item:Object):String {
if (item && item as SalesPerson && item.lastName && item.firstName) {
return item.firstName + "," + item.lastName;
}
return "";
}
private var arr:ArrayCollection;
private var arr1:ArrayCollection;
private var salesPer:SalesPerson;
private function getData():ArrayCollection
{
arr1 = new ArrayCollection();
var salesPerson:SalesPerson = new SalesPerson();
salesPerson.userName = "ravi kumar";
salesPerson.firstName = "ravi";
salesPerson.lastName = "kumar";
var salesPerson1:SalesPerson = new SalesPerson();
salesPerson1.userName = "kiran kumar";
salesPerson1.firstName = "kiran";
salesPerson1.lastName = "kumar";
var salesPerson2:SalesPerson = new SalesPerson();
salesPerson2.userName = "james bond";
salesPerson2.firstName = "james";
salesPerson2.lastName = "bond";
var salesPerson3:SalesPerson = new SalesPerson();
salesPerson3.userName = "ravi babu";
salesPerson3.firstName = "ravi";
salesPerson3.lastName = "babu";
var salesPerson4:SalesPerson = new SalesPerson();
salesPerson4.userName = "rakesh babu";
salesPerson4.firstName = "rakesh";
salesPerson4.lastName = "babu";
var salesPerson5:SalesPerson = new SalesPerson();
salesPerson5.userName = "ramesh babu";
salesPerson5.firstName = "ramesh";
salesPerson5.lastName = "babu";
var salesPerson6:SalesPerson = new SalesPerson();
salesPerson6.userName = "aram babu";
salesPerson6.firstName = "aram";
salesPerson6.lastName = "babu";
var salesPerson7:SalesPerson = new SalesPerson();
salesPerson7.userName = "armu babu";
salesPerson7.firstName = "armu";
salesPerson7.lastName = "babu";
arr1.addItem(salesPerson);
arr1.addItem(salesPerson1);
arr1.addItem(salesPerson2);
arr1.addItem(salesPerson3);
arr1.addItem(salesPerson4);
arr1.addItem(salesPerson5);
arr1.addItem(salesPerson6);
arr1.addItem(salesPerson7);
return arr1;
}
]]></fx:Script>
<s:VGroup width="100%" height="100%">
<local:FilterCombo labelFunction="labelField" dataProvider="{getData()}"/>
</s:VGroup>
</s:Application>
<?xml version="1.0"?>
<s:ComboBox xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx" click="clickHandler(event)">
<fx:Script>
<![CDATA[
import mx.collections.ArrayCollection;
import mx.collections.IList;
import spark.events.TextOperationEvent;
private var unfilteredDataProvider:IList;
override public function set dataProvider(value:IList):void {
super.dataProvider = value;
unfilteredDataProvider = value;
}
override protected function textInput_changeHandler(event:TextOperationEvent):void {
super.textInput_changeHandler(event);
if (unfilteredDataProvider is ArrayCollection) {
ArrayCollection(unfilteredDataProvider).filterFunction = filterMatches;
ArrayCollection(unfilteredDataProvider).refresh();
super.dataProvider = new ArrayCollection(unfilteredDataProvider.toArray());
}
}
protected function filterMatches(item:Object):Boolean {
if (item && item.lastName && item.firstName) {
if (String(item.lastName + item.firstName).toLowerCase().indexOf(textInput.text.slice(0, textInput.selectionAnchorPosition).toLowerCase()) > -1) {
// trace("traderDoFilter true")
return true;
}
}
return false;
}
private function clickHandler(event:MouseEvent):void {
}
]]>
</fx:Script>
</s:ComboBox>
Basically Combobox search is working based on labelfield, you can see the Combobox framework code.
Verify the below mentioned function:
ComboBox -> processInputField(Function)
if (itemMatchingFunction != null)//itemMatchingFunction allways null untill we assign our callback function
matchingItems = itemMatchingFunction(this, textInput.text);
else
matchingItems = findMatchingItems(textInput.text);//calling by default
So we need to assign our custom callbackfunction to itemMatchingFunction(public)
I have made some changes in your code try this, it has some bugs
<?xml version="1.0" encoding="utf-8"?>
<s:ComboBox xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx" click="clickHandler(event)">
<fx:Script>
<![CDATA[
import mx.collections.ArrayCollection;
import mx.collections.IList;
import spark.events.TextOperationEvent;
import spark.utils.LabelUtil;
private var unfilteredDataProvider:IList;
namespace mx_internal;
override public function set dataProvider(value:IList):void {
super.dataProvider = value;
this.itemMatchingFunction = itemMatchingFunction1;
}
override protected function textInput_changeHandler(event:TextOperationEvent):void {
super.textInput_changeHandler(event);
if (dataProvider is ArrayCollection) {
ArrayCollection(dataProvider).filterFunction = filterMatches;
ArrayCollection(dataProvider).refresh();
}
}
protected function filterMatches(item:Object):Boolean {
if (item && item.lastName && item.firstName) {
if (String(item.lastName +","+ item.firstName).toLowerCase().indexOf(textInput.text.slice(0, textInput.selectionAnchorPosition).toLowerCase()) > -1) {
return true;
}
}
return false;
}
/**
* #private
*/
// Returns an array of possible values
private function itemMatchingFunction1(comB:ComboBox,input:String):Vector.<int>
{
// For now, just select the first match
var startIndex:int;
var stopIndex:int;
var retVal:int;
var retVector:Vector.<int> = new Vector.<int>;
retVal = findStringLoop(input, 0, dataProvider.length);
if (retVal != -1)
retVector.push(retVal);
return retVector;
}
/**
* #private
*/
function findStringLoop(str:String, startIndex:int, stopIndex:int):Number
{
// Try to find the item based on the start and stop indices.
for (startIndex; startIndex != stopIndex; startIndex++)
{
var itmStr:String = itemToLabel(dataProvider.getItemAt(startIndex));
itmStr = itmStr.substring(0, str.length);
if (str == itmStr || str.toUpperCase() == itmStr.toUpperCase())
{
return startIndex;
}
}
return -1;
}
/**
* Given a data item, return the correct text a renderer
* should display while taking the <code>labelField</code>
* and <code>labelFunction</code> properties into account.
*
* #param item A data item
*
* #return String representing the text to display for the
* data item in the renderer.
*
* #langversion 3.0
* #playerversion Flash 10
* #playerversion AIR 1.5
* #productversion Flex 4
*/
override public function itemToLabel(item:Object):String
{
if (item && item.lastName && item.firstName)
return item.lastName +","+ item.firstName;
return item[labelField];
}
]]>
</fx:Script>
</s:ComboBox>

Adobe record sound and save

In the following code i am trying to save the microphone contents to a file.The saved file doesn't play and Every time the file is saved i see that the size is only of 10 bytes only.What am i doing wrong in the code.Can someone please show me the correct code to save it .And the saved file should play the recorded contents accordingly.
<?xml version="1.0" encoding="utf-8"?>
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx" minWidth="955" minHeight="600">
<fx:Script>
<![CDATA[
import flash.events.SampleDataEvent;
import flash.media.Microphone;
import flash.net.FileReference;
import mx.controls.Alert;
import flash.net.FileReference;
import flash.display.Sprite;
import flash.media.Sound;
import flash.utils.ByteArray;
import flash.external.ExternalInterface;
public var _file:FileReference = new FileReference();
[Bindable] private var micList:Array;
public var mic:Microphone = Microphone.getMicrophone();
protected var isRecording:Boolean = false;
protected function startMicRecording():void
{
//var mic:Microphone = Microphone.getMicrophone();
mic.gain = 60;
mic.rate = 11;
mic.setUseEchoSuppression(true);
mic.setLoopBack(true);
mic.setSilenceLevel(5, 1000);
Alert.show("In recording");
isRecording = true;
mic.addEventListener(SampleDataEvent.SAMPLE_DATA, gotMicData);
}
protected function stopMicRecording():void
{
//isRecording = false;
try{
//_file.save( SampleDataEvent.SAMPLE_DATA, "recorded.wav" );
_file.save(SampleDataEvent.SAMPLE_DATA , "recorded.flv" );
}
catch(e:Error)
{
Alert.show("In Stopmicrecording"+e);
}
}
private function gotMicData(micData:SampleDataEvent):void
{
//mic.removeEventListener(SampleDataEvent.SAMPLE_DATA, gotMicData);
}
protected var soundRecording:ByteArray;
protected var soundOutput:Sound;
protected function playbackData():void
{
}
private function playSound(soundOutput:SampleDataEvent):void
{
}
]]>
</fx:Script>
<fx:Declarations>
<!-- Place non-visual elements (e.g., services, value objects) here -->
</fx:Declarations>
<mx:ComboBox x="150" id="comboMicList" dataProvider="{micList}" />
<mx:Button x="250" id="startmicrec" label="Start Rec" click="startMicRecording()"/>
<mx:Button x="350" id="stopmicrec" label="Stop Rec" click="stopMicRecording()"/>
<!--<mx:Button x="50" id="setupmic" label="Select Mic" click="setupMicrophone()"/>-->
<mx:Button x="450" id="playrecsound" label="Play sound" click="playbackData()"/>
</s:Application>
You need to store the data that is handed to you in gotMicData into a ByteArray and then save that ByteArray. You are saving the event name, which is a string (10 characters long).
Once you do that, you need to load the file and hand sample data to the sound. You play the sound back 8 times... because you sampled at 11 KHz but the sound plays back at 44 KHz (4x writing) and the sound is Stereo but the mic is mono (2x again).
You can't save the data as a WAV file directly... you recorded raw data. If you want to go through the trouble of writing a proper WAV header, then you don't have to play the games of handing sample data and hand the file to the Sound object. That is an exercise outside of the scope of this question.
Good luck!
import mx.controls.Alert;
public var mic:Microphone = Microphone.getMicrophone();
public var recordedData:ByteArray;
protected function startMicRecording():void
{
mic.gain = 60;
mic.rate = 11;
mic.setUseEchoSuppression(true);
mic.setLoopBack(false);
mic.setSilenceLevel(5, 1000);
recordedData = new ByteArray();
mic.addEventListener(SampleDataEvent.SAMPLE_DATA, gotMicData);
}
protected function stopMicRecording():void
{
mic.removeEventListener(SampleDataEvent.SAMPLE_DATA, gotMicData);
try{
var file:FileReference = new FileReference();
file.save(recordedData, "recorded.dat" );
}
catch(e:Error)
{
Alert.show("In Stopmicrecording"+e);
}
}
private function gotMicData(sample:SampleDataEvent):void
{
recordedData.writeBytes(sample.data, 0, sample.data.bytesAvailable);
}
protected var playbackFile:FileReference;
protected var soundRecording:ByteArray;
protected var soundOutput:Sound;
protected function playbackData():void
{
playbackFile = new FileReference();
playbackFile.addEventListener(Event.SELECT, playbackFileSelected);
playbackFile.browse();
}
private function playbackFileSelected(event:Event):void {
playbackFile.addEventListener(Event.COMPLETE, playbackFileLoaded);
playbackFile.load();
}
private function playbackFileLoaded(event:Event):void {
soundRecording = playbackFile.data;
soundOutput = new Sound();
soundOutput.addEventListener(SampleDataEvent.SAMPLE_DATA, moreInput);
soundOutput.play();
}
private function moreInput(event:SampleDataEvent):void {
var sample:Number;
for (var i:int = 0; i < 1024; i++) {
if (soundRecording.bytesAvailable > 0) {
sample = soundRecording.readFloat();
// write the same byte 8 times:
// Upsample from 11 KHz to 44 KHz (x4)
// Mono to Stereo (x2)
for(var x:int = 0; x < 8; x++)
event.data.writeFloat(sample);
}
}
}

red5 streaming connection to flex

I installed red5 successfully, but when I try to connect to red5 to stream a video, the connection fails. If I use netstreaming(null), it works, but when I use red5, it doesn't.
I use following code to connect the stream:
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx" minWidth="955" minHeight="600" creationComplete="init();">
<fx:Script>
<![CDATA[
import mx.utils.ObjectUtil;
private var nc:NetConnection;
private var ns:NetStream;
private var video:Video;
private var meta:Object;
private var videoURL:String = "Fleximagteaser.flv";
private var nc1:NetConnection;
private var ns1:NetStream;
private var video1:Video;
private var meta1:Object;
private function init():void {
//video1
var nsClient:Object = {};
nsClient.onMetaData = ns_onMetaData;
nsClient.onCuePoint = ns_onCuePoint;
nc = new NetConnection();
nc.connect("rtmp://localhost/demo");
ns = new NetStream(nc);
ns.play(videoURL);
ns.client = nsClient;
video = new Video();
video.attachNetStream(ns);
uic.addChild(video);
}
private function ns_onMetaData(item:Object):void {
trace("meta");
meta = item;
// Resize Video object to same size as meta data.
video.width = item.width;
video.height = item.height;
// Resize UIComponent to same size as Video object.
uic.width = video.width;
uic.height = video.height;
panel.title = "framerate: " + item.framerate;
panel.visible = true;
trace(ObjectUtil.toString(item));
}
private function ns_onCuePoint(item:Object):void {
trace("cue");
}
]]>
</fx:Script>
<fx:Declarations>
<!-- Place non-visual elements (e.g., services, value objects) here -->
</fx:Declarations>
<mx:VBox>
<mx:Panel id="panel" visible="false">
<mx:UIComponent id="uic" />
<mx:ControlBar>
<mx:Button label="Play/Pause" click="ns.togglePause();" />
<mx:Button label="Rewind" click="ns.seek(0); ns.pause();" />
</mx:ControlBar>
</mx:Panel>
</mx:VBox>
</s:Application>
Can anyone help?
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx" minWidth="955" minHeight="600" creationComplete="init();">
<fx:Script>
<![CDATA[
import flash.globalization.Collator;
import mx.utils.ObjectUtil;
private var nc:NetConnection;
private var ns:NetStream;
private var video:Video;
private var meta:Object;
private var videoURL:String = "Fleximagteaser.flv";
private var nc1:NetConnection;
private var ns1:NetStream;
private var video1:Video;
private var meta1:Object;
private function init():void {
//video1
nc = new NetConnection();
nc.connect("rtmp");
nc.client = this;
nc.addEventListener(NetStatusEvent.NET_STATUS,onConnectionStatus);
nc.addEventListener(AsyncErrorEvent.ASYNC_ERROR,onErrorHandler);
nc.addEventListener(SecurityErrorEvent.SECURITY_ERROR, onSecurityError);
}
private function onConnectionStatus(event:NetStatusEvent):void
{
var nsClient:Object = {};
nsClient.onMetaData = ns_onMetaData;
nsClient.onCuePoint = ns_onCuePoint;
ns = new NetStream(nc);
ns.play("videourl");
ns.client = nsClient;
video = new Video();
video.attachNetStream(ns);
uic.addChild(video);
}
private function onErrorHandler(event:AsyncErrorEvent):void{}
private function onSecurityError(event:SecurityErrorEvent):void{}
private function ns_onMetaData(item:Object):void {
trace("meta");
meta = item;
// Resize Video object to same size as meta data.
video.width = item.width;
video.height = item.height;
// Resize UIComponent to same size as Video object.
uic.width = video.width;
uic.height = video.height;
panel.title = "framerate: " + item.framerate;
panel.visible = true;
trace(ObjectUtil.toString(item));
}
private function ns_onCuePoint(item:Object):void {
trace("cue");
}
public function onBWDone():void
{}
]]>
</fx:Script>
<fx:Declarations>
<!-- Place non-visual elements (e.g., services, value objects) here -->
</fx:Declarations>
<mx:VBox>
<mx:Panel id="panel" visible="false">
<mx:UIComponent id="uic" />
<mx:ControlBar>
<mx:Button label="Play/Pause" click="ns.togglePause();" />
<mx:Button label="Rewind" click="ns.seek(0); ns.pause();" />
</mx:ControlBar>
</mx:Panel>
</mx:VBox>

How can I get a mx:textarea height to be the same as the content

The initial height of a text area is much larger than the content, I cannot find a way of making it always the same height as the text content:
<mx:TextArea id="textarea" borderStyle="solid" width="100%" wordWrap="true" selectable="false" backgroundAlpha="0" focusAlpha="0" text="this is a little test" />
Gives a bordered box that is much taller than needed.
This also gives an unintential problem if you have links within the content in that a link 'mouseover' is triggered when nowhere near the link.
<mx:Script>
<![CDATA[
public function onInit():void
{
var style:StyleSheet = new StyleSheet();
var aLink:Object = new Object();
aLink.color = "#0000FF";
var aHover:Object = new Object();
aHover.color = "#00FF00";
aHover.textDecoration = "underline";
style.setStyle( "a:hover", aHover );
style.setStyle( "a:link", aLink );
textarea.styleSheet = style;
}
]]>
</mx:Script>
<mx:TextArea id="textarea" width="100%" wordWrap="true" borderStyle="solid" selectable="false" backgroundAlpha="0" focusAlpha="0" >
<mx:htmlText>
<![CDATA[<a href='event:http://www.adobe.com'>Navigate to Adobe.com.</a> this is testing nothing at all really]]>
</mx:htmlText>
</mx:TextArea>
The Text component doesnt suffer from this, but I cannot attach a stylesheet to a text component.
Hoping someone can help. Or is there some other component I can use where I can add a stylesheet to stylise anchor tags.
I found this overridable in the TextArea.as source and if I override it and remove the "2 x" multiplier it almost works but unfortunately it means that the content doesnt get bigger when it needs to and vertically scrolls instead, so its almost there:
override protected function measure():void
{
super.measure();
measuredMinWidth = DEFAULT_MEASURED_MIN_WIDTH;
measuredWidth = DEFAULT_MEASURED_WIDTH;
// TextArea is minimum of two lines of text
measuredMinHeight = measuredHeight = 2 * DEFAULT_MEASURED_MIN_HEIGHT;
}
If you extend Text, you can add a getter/setter that allows you to set the styleSheet of the underlying UITextField object.
package
{
import flash.events.Event;
import flash.text.StyleSheet;
import mx.controls.Text;
import mx.core.mx_internal;
use namespace mx_internal;
public class StyledText extends Text
{
public function StyledText()
{
super();
}
private var _styleSheet:StyleSheet = null;
[Bindable("stylesheetChanged")]
public function get styleSheet():StyleSheet {
return _styleSheet;
}
public function set styleSheet(value:StyleSheet):void {
_styleSheet = value;
if ( textField ) {
textField.styleSheet = _styleSheet;
}
dispatchEvent(new Event("stylesheetChanged"));
}
override protected function createChildren():void {
super.createChildren();
//textField is created in the createChildren
//method of the Label class
if ( textField && styleSheet ) {
textField.styleSheet = _styleSheet;
}
}
}
}
Then you can use the component like so:
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" xmlns:ns1="*" preinitialize="onInit()">
<mx:Script>
<![CDATA[
public function onInit():void
{
var style:StyleSheet = new StyleSheet();
var aLink:Object = new Object();
aLink.color = "#0000FF";
var aHover:Object = new Object();
aHover.color = "#00FF00";
aHover.textDecoration = "underline";
style.setStyle( "a:hover", aHover );
style.setStyle( "a:link", aLink );
text.styleSheet = style;
}
]]>
</mx:Script>
<ns1:StyledText id="text" x="0" y="79">
<ns1:htmlText>
<![CDATA[<a href='event:http://www.adobe.com'>Navigate to Adobe.com.</a> this is testing nothing at all really]]>
</ns1:htmlText>
</ns1:StyledText>
</mx:Application>
I haven't tried what you're attempting, but this link looks like it might help:
http://www.adobe.com/cfusion/communityengine/index.cfm?event=showdetails&postId=13628&productId=2.
Based on Bedwyr's link, I thought I would try recalcing the height myself and this seems to work fine (not noticed any bad side-effects yet, but there may be):
this.addEventListener( Event.CHANGE, onReMeasure );
this.addEventListener( Event.RESIZE, onReMeasure );
override protected function measure():void
{
super.measure();
measuredMinWidth = DEFAULT_MEASURED_MIN_WIDTH;
measuredWidth = DEFAULT_MEASURED_WIDTH;
var lm:TextLineMetrics = getLineMetrics( 0 );
measuredMinHeight = measuredHeight = DEFAULT_MEASURED_MIN_HEIGHT;
}
private function onReMeasure( eventObj:Event ):void
{
var ht:Number = 0;
for( var n:int = 0; n < textField.numLines; n++ )
{
ht += textField.getLineMetrics(n).height;
}
ht += 10; // padding
height = ht;
validateNow();
}