how to create a text stepper control in flex?
I need a control in Flex 3 that is like NumericStepper, but that can display arbitrary strings. Does this control exist? If not, what are your suggestions for creating it, or reference开发者_运维知识库s you would recommend?
For convenience, I'm calling this a TextStepper. I want this as a compact way to display a list of string choices that a user can cycle through by clicking the up/down buttons. Compact means no drop-down or pop-up aspects of the control: the only way to change the selected index is to click the up/down button (which updates the text input value). Value cycling means that I really want to treat the underlying dataProvider as a circular buffer. So up/down clicks modify selectedIndex in modulo fashion.
The idea is to use valueFormatFunction
:
<?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:StringStepper horizontalCenter="0" verticalCenter="0" width="200">
<local:dataProvider>
<s:ArrayCollection>
<fx:String>Hello!</fx:String>
<fx:String>I love you.</fx:String>
<fx:String>Won't you tell me your name?</fx:String>
</s:ArrayCollection>
</local:dataProvider>
</local:StringStepper>
</s:Application>
Source for StringStepper:
package
{
import mx.collections.ArrayCollection;
import mx.events.CollectionEvent;
import spark.components.NumericStepper;
public class StringStepper extends NumericStepper
{
public function StringStepper()
{
enabled = false;
valueFormatFunction = defaultValueFormatFunction;
valueParseFunction = defaultValueParseFunction;
}
private var _dataProvider:ArrayCollection;
public function get dataProvider():ArrayCollection
{
return _dataProvider;
}
public function set dataProvider(value:ArrayCollection):void
{
if (_dataProvider == value)
return;
if (_dataProvider)
_dataProvider.removeEventListener(CollectionEvent.COLLECTION_CHANGE,
dataProvider_collectionChangeHandler);
_dataProvider = value;
commitDataProvider();
if (_dataProvider)
_dataProvider.addEventListener(CollectionEvent.COLLECTION_CHANGE,
dataProvider_collectionChangeHandler);
}
/**
* Same event as for <code>value</code>.
*/
[Bindable("valueCommit")]
public function get selectedItem():Object
{
return _dataProvider && value <= _dataProvider.length - 1 ? _dataProvider[value] : null;
}
public function set selectedItem(value:Object):void
{
if (!_dataProvider)
return;
value = _dataProvider.getItemIndex(value);
}
private function defaultValueFormatFunction(value:Number):String
{
return _dataProvider && value <= _dataProvider.length - 1 ? _dataProvider[value] : String(value);
}
private function defaultValueParseFunction(value:String):Number
{
if (!_dataProvider)
return 0;
var n:int = _dataProvider.length;
for (var i:int = 0; i < n; i++)
{
var string:String = _dataProvider[i];
if (string == value)
return i;
}
return 0;
}
private function commitDataProvider():void
{
if (!_dataProvider)
{
minimum = 0;
maximum = 0;
enabled = false;
return;
}
enabled = true;
minimum = 0;
maximum = _dataProvider.length - 1;
}
private function dataProvider_collectionChangeHandler(event:CollectionEvent):void
{
commitDataProvider();
}
}
}
I created one of these (as an MXML comoponent) by overlaying a TextInput
over a NumericStepper
(absolutely positioned) so that the TextInput
covered the input portion of the NumericStepper
.
The dataProvider was an ArrayCollection
of strings, and the value of the NumericStepper
was used to access an index in the ArrayCollection.
The change event of the NumericStepper
changed the text of the TextInput
to whatever was at index n of the dataProvider. I gave the component an editable property, which set the TextInput
to editable and inserted the new string into the dataProvider at the current index.
精彩评论