как создать текстовый шаговый элемент управления во флексе?

Мне нужен элемент управления в Flex 3, который похож на NumericStepper, но может отображать произвольные строки. Этот контроль существует? Если нет, каковы ваши предложения по его созданию или ссылки, которые вы бы порекомендовали?

Для удобства я называю это TextStepper. Я хочу, чтобы это был компактный способ отображения списка вариантов строки, который пользователь может циклически перебирать, нажимая кнопки вверх / вниз. Компактность означает отсутствие раскрывающихся или всплывающих окон элемента управления: единственный способ изменить выбранный индекс - это нажать кнопку вверх / вниз (которая обновляет значение ввода текста). Цикл значений означает, что я действительно хочу рассматривать базовый dataProvider как кольцевой буфер. Таким образом, щелчки вверх / вниз изменяют selectedIndex по модулю.


person Andrew B.    schedule 26.06.2010    source источник


Ответы (2)


Идея состоит в том, чтобы использовать 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>

Источник для 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();
    }

}
}
person Maxim Kachurovskiy    schedule 26.06.2010
comment
Максим, как это изменится для Flex 3? - person Andrew B.; 26.06.2010
comment
Для Flex 3 самый простой способ описан в комментарии Робусто. NumericStepper в Flex 3 по-моему не настраивается. - person Maxim Kachurovskiy; 27.06.2010

Я создал один из них (как компонент MXML), наложив TextInput на NumericStepper (с абсолютным позиционированием) так, чтобы TextInput покрыл входную часть NumericStepper.

DataProvider был ArrayCollection строк, а значение NumericStepper использовалось для доступа к индексу в ArrayCollection.

Событие изменения NumericStepper изменило текст TextInput на то, что было в индексе n поставщика данных. Я дал компоненту редактируемое свойство, которое установило для TextInput значение editable и вставило новую строку в dataProvider по текущему индексу.

person Robusto    schedule 26.06.2010