See the simple application created below. I have a RichTextEditor and a RichText component. The idea is to display whatever typed in the RichTextEditor in the RichText component. Everything else (I think) works except for Bullets! The conversion works as if bullets don't exist!
<?xml version="1.0" encoding="utf-8"?>
<s:Application width="100%"
height="100%"
xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx">
<s:layout>
<s:HorizontalLayout />
</s:layout>
<fx:Script>
<![CDATA[
import flashx.textLayout.conversion.TextConverter;
import mx.events.FlexEvent;
protected function convert_clickHandler(event:MouseEvent):void
{
richText.textFlow = TextConverter.importToFlow(editor.htmlText, TextConverter.TEXT_FIELD_HTML_FORMAT);
}
]]>
</fx:Script>
<mx:RichTextEditor id="editor" />
<s:Button id="convert" click="convert_clickHandler(event)" />
<s:RichText id="richText" />
</s:Application>
Any idea on how to make Bullets work with RichText ? Am I using the correct conversion method ? TextConverter.importToFlow ?
See the image below.
List items are not a supported by TEXT_FIELD_HTML_FORMAT. You would need to create your own editor that supports the added TextFlow functionality. There is an example of one such editor in Tour de' Flex, but it was written prior to list support in TLF 2. I'm not sure if it's been updated, but if not you will need to add in that functionality yourself.
Good luck!
Related
In a Flex Mobile app I would like to have a ButtonBar at the bottom and I need to change the labels of its buttons:
(I don't want to use TabbedViewNavigatorApplication here, because all my logic is in a single View with an ActionBar at its top and ButtonBar at its bottom).
So I have prepared a very simple test case to demonstrate my problem.
Please just create a "blank" Flex mobile project in Flash Builder and put my 2 files (below) into it and you will see my problem - touching the buttons at the bottom doesn't change the label of the very right button).
TestAC.mxml:
<?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"
applicationDPI="160">
<fx:Script>
<![CDATA[
import spark.events.IndexChangeEvent;
import spark.skins.mobile.TabbedViewNavigatorTabBarSkin;
private function handleTabs(event:IndexChangeEvent):void {
trace(_tabBar.selectedIndex);
_tabs[2].label = String(1 + _tabBar.selectedIndex);
}
]]>
</fx:Script>
<fx:Declarations>
<s:MultiDPIBitmapSource id="CHAT"
source160dpi="#Embed('chat.png')"
source240dpi="#Embed('chat.png')"
source320dpi="#Embed('chat.png')" />
<s:ArrayCollection id="_tabs">
<fx:Object label="One" />
<fx:Object label="Two" />
<fx:Object label="Three" icon="{CHAT}" />
</s:ArrayCollection>
</fx:Declarations>
<s:ButtonBar id="_tabBar"
requireSelection="true"
width="100%"
bottom="0"
skinClass="spark.skins.mobile.TabbedViewNavigatorTabBarSkin"
dataProvider="{_tabs}"
change="handleTabs(event)">
</s:ButtonBar>
</s:Application>
chat.png:
Allright, adding _tabs.refresh(); to handleTabs has helped.
I have got a SkinnableComponent:
public class ContentView extends SkinnableComponent
{
[Bindable]
public var titleBar:IVisualElement;
public function ContentView(pContentXML:XML)
{
this.setStyle("skinClass", ContentViewSkin );
}
}
and now i want to display the titleBar in the mxml skin file.
<?xml version="1.0" encoding="utf-8"?>
<s:Skin xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark">
<fx:Metadata>
[HostComponent("EMM.App2Go.Viewer.Component.ContentView")]
</fx:Metadata>
<s:DataGroup width="100%" >
<s:dataProvider>
<s:ArrayList source="{hostComponent.titleBar}" />
</s:dataProvider>
</s:DataGroup>
as you can see I managed it with a DataGroup but this is kind of ugly, and I was thinking about an easier way to do this like
<fx:Object source="hostComponent.titleBar" />
or something like that.
I hope you can help me.
You seem to have a deep misunderstanding of how the Spark SKinning Model should work. You should not reference the hostComponent from the skin in order to display items. You should create the element in the skin; and use the same name. So if the hostComponent has a skin part defined like this:
[Bindable]
[SkinPart]
public var titleBar:IVisualElement;
the skin should have something like this:
<s:DataGroup width="100%" id="titleBar" >
</s:DataGroup>
I suggest reading through this information on Spark Skinning, and also learn the Component LifeCycle.
how to I pass in a uicomponent to a mxml custom component?
ex: I want to pass in any number of buttons, and I want my custom component to lay them out in a certain order.
MainApp.mxml:
<?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" xmlns:local="*"
>
<local:myComp >
<s:Button label='Button1' />
<s:Button label='Button2' />
<!--I want to add anything else here -->
</local:myComp>
myComp.mxml:
<?xml version="1.0" encoding="utf-8"?>
<s:Group xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx"
creationComplete="init()"
width="400" height="300"
>
<fx:Script>
<![CDATA[
private function init():void {
// how do I access the added components and place them where I want?
// do I use removeChildren and AddChildren?
// addItemsHere.addchild(nextButton);
]]>
</fx:Script>
<s:HGroup id='addItemsHere' />
As your component extends Group, you shall use addElement instead of addChild (and for all other methods with 'child' in their name it shall be replaced with 'element'. So, access to all elements will be like that:
for(var i:int =0; i < numElements; i++){
var button:Button = Button(getElementAt(i));
doWhatIWantWithMyButton(button);
}
It is also better to override createChildren method of your component if you know what to add at the creation moment.
If you don't need very specific button placement, you can set layout property of your component to any desired layout (like VerticalLayout, for example), and those layouts are tunable.
You seem to be trying to recreate functionality that already exists in the SDK. This is wat SkinnableContainer is for.
Depending on your use case, there are two ways to use it:
You only need to add some custom graphic elements to you custom component, but no additional behaviour
In this scenario, you would simple reuse SkinnableContainer and assign it a custom skin, like so:
<s:SkinnableContainer skinClass="MySkin">
<s:Button label='Button1' />
<s:Button label='Button2' />
</s:SkinnableContainer>
With MySkin.mxml perhaps something like:
<s:Skin xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark">
<fx:Metadata>
[HostComponent("spark.components.SkinnableContainer")]
</fx:Metadata>
<s:states>
<s:State name="normal" />
<s:State name="disabled" />
</s:states>
<s:layout>
<s:VerticalLayout/>
</s:layout>
<s:Label text="I'm a SkinnableContainer"/>
<s:Group id="contentGroup" width="100%" height="100%">
</s:SkinnableContainer>
Your Buttons will now automatically be added to the contentGroup; the SkinnableContainer class handles this for you. Note that this Group must have exactly that id; it's a required SkinPart.
You want to add some behaviour to you component
The procedure is the same, but you would now subclass SkinnableContainer (this is usually done in pure ActionScript), write some behaviour in there, and assign the skin to an instance of this class.
public class MyComp extends SkinnableContainer {
//additional behaviour goes here
}
Usage:
<local:MyComp skinClass="MySkin">
<s:Button label='Button1' />
<s:Button label='Button2' />
</local:MyComp>
I'm making simple editor. And I want that, let write replacing colorless text to color text from RichEditableText when I will write any text.
For example:
PHP --> <s:span color="#FF0000">PHP<s:span>
This codes not work:
editorum.text = editorum.text.replace('PHP','<s:span color="#FF0000">php<s:span>');
Editorum is: <s:RichEditableText id="editorum" ></s:RichEditableText>
Click here and try
Source code:
<?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"
width="319" height="198" minWidth="955" minHeight="600">
<fx:Style source="ops.css"/>
<fx:Declarations>
<!-- Place non-visual elements (e.g., services, value objects) here -->
</fx:Declarations>
<fx:Script>
<![CDATA[
import flashx.textLayout.formats.TextLayoutFormat;
import mx.collections.ArrayCollection;
import mx.events.FlexEvent;
import spark.events.TextOperationEvent;
import spark.utils.TextFlowUtil;
protected function editorum_changeHandler(event:TextOperationEvent):void
{
editorum.text = editorum.text.replace('melon','<s:span color="#FF0000">melon<s:span>');
}
]]>
</fx:Script>
<s:RichEditableText id="editorum" x="10" y="28" width="299" height="159"
change="editorum_changeHandler(event)">
</s:RichEditableText>
<s:Label x="10" y="10" width="119" text="Write 'melon' :"/>
</s:Application>
A other problem; How do I send the pointer at the end? When I press any key, pointer going to deal. Try: http://samed.us/samples/ops3.swf
Thanks for your help...
Instead of this line:
editorum.text = editorum.text.replace('melon','<s:span color="#FF0000">melon<s:span>');
Try something like this:
var text : String = editorum.text.replace('melon','<s:span color="#FF0000">melon<s:span>')
editorum.textFlow = TextConverter.importToFlow(text, TextConverter.TEXT_FIELD_HTML_FORMAT);
Basically, you need to convert the HTML into something that the TLF Framework will understand. Read some docs on textFlow and the TextConverter
I want to build a component, where the user can play a video in a Flex Spark VideoDisplay. There will be a button and whenever the button is pressed, I want to save the current time of the VideoDisplay plus a screenshot. The screenshot needs to be someway saved, because I want to display all times and screenshots in a DataGrid (screenshots should appear when the user hovers a time in the DataGrid).
So, how can I take screenshots of the Spark VideoDisplay and save/display them?
You can take snapshots a few ways, this way just uses the ImageSnapshot class, but you could do it by manually drawing the bitmap of the video display if you'd like. Here's a sample:
Renderer
<?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"
width="100" height="100" creationComplete="trace(data)">
<mx:Image source="{this.data}" width="100%" height="100%"/>
</s:ItemRenderer>
Sample App
<?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">
<fx:Script>
<![CDATA[
import mx.graphics.ImageSnapshot;
public function takeSnapshot():void
{
var snapshot:BitmapData = ImageSnapshot.captureBitmapData(videoDisplay);
var bitmap:Bitmap = new Bitmap(snapshot);
list.dataProvider.addItem(bitmap);
}
]]>
</fx:Script>
<s:layout>
<s:VerticalLayout horizontalAlign="center"/>
</s:layout>
<s:VideoDisplay id="videoDisplay"
source="video.mov"
width="400" height="300"/>
<s:Button id="button" click="takeSnapshot()"/>
<s:List id="list" horizontalCenter="0" width="100%" itemRenderer="SnapshotRenderer">
<s:dataProvider>
<mx:ArrayList/>
</s:dataProvider>
<s:layout>
<s:TileLayout/>
</s:layout>
</s:List>
</s:Application>
To accomplish exactly what you were describing (take snapshot and save snapshot), you could store those in an array in that takeSnapshot method, or you could loop through the list.dataProvider do get the bitmaps. Then you'd just need to pass them to a backend language (ruby, python, php...) to save.
Hope that helps,
Lance
use the JPEGEncoder in flex to convert it to bytearray, and then encode the byte array using the b64encoder as follow:
var jpg:JPEGEncoder = new JPEGEncoder();
var ba:ByteArray = jpg.encode(bitmapData);
var b64encoder:Base64Encoder = new Base64Encoder();
b64encoder.encodeBytes(ba);
var b64String:String = b64encoder.flush();
Now you can pass your b64String to your server via HTTP post method :)