Flex: Custom Item Renderer For Combobox управляет усечением текста - PullRequest
1 голос
/ 19 сентября 2008

Я реализовал пользовательский рендерер элементов, который я использую со списком в проекте Flex, над которым я работаю. Он отображает и значок, и текст для каждого элемента. Единственная проблема заключается в том, что при длинном тексте ширина меню не корректируется должным образом, и текст отображается при отображении. Я пытался настроить все очевидные свойства, чтобы облегчить эту проблему, но не имел никакого успеха. Кто-нибудь знает, как сделать так, чтобы ширина меню комбинированного списка масштабировалась в соответствии с данными, которые он отображает?

Моя реализация средства визуализации пользовательских элементов:

<?xml version="1.0" encoding="utf-8"?>
<mx:HBox xmlns:mx="http://www.adobe.com/2006/mxml"
    styleName="plain" horizontalScrollPolicy="off"> 

    <mx:Image source="{data.icon}" />
    <mx:Label text="{data.label}" fontSize="11" fontWeight="bold" truncateToFit="false"/>

</mx:HBox>

И мой комбобокс использует это так:

    <mx:ComboBox id="quicklinksMenu" change="quicklinkHandler(quicklinksMenu.selectedItem.data);" click="event.stopImmediatePropagation();" itemRenderer="renderers.QuickLinkItemRenderer" width="100%"/>

EDIT: Я должен уточнить кое-что: я могу установить для свойства dropdownWidth в выпадающем списке какое-то произвольно большое значение - это все подойдет, но оно будет слишком широким. Так как данные, отображаемые в этом комбинированном окне, являются общими, я хочу, чтобы они автоматически определяли размер самого большого элемента в поставщике данных (документация по гибкому шину говорит, что это будет сделано, но у меня есть ощущение, что мой пользовательский рендерер элементов каким-то образом нарушает это поведение)

Ответы [ 5 ]

1 голос
/ 19 сентября 2008

Просто случайная мысль (без подсказки, поможет ли это):

Попробуйте установить родительский HBox и ширину метки на 100%. Это, как правило, исправляло любые проблемы, с которыми я сталкивался, которые были похожи.

0 голосов
/ 06 ноября 2009

Если вы посмотрите на measure метод mx.controls.ComboBase, вы увидите, что comboBox вычисляет его measuredMinWidth как сумму ширины текста и ширины кнопки comboBox.

    // Text fields have 4 pixels of white space added to each side
    // by the player, so fudge this amount.
    // If we don't have any data, measure a single space char for defaults
    if (collection && collection.length > 0)
    {
        var prefSize:Object = calculatePreferredSizeFromData(collection.length);

        var bm:EdgeMetrics = borderMetrics;

        var textWidth:Number = prefSize.width + bm.left + bm.right + 8;
        var textHeight:Number = prefSize.height + bm.top + bm.bottom 
                    + UITextField.TEXT_HEIGHT_PADDING;

        measuredMinWidth = measuredWidth = textWidth + buttonWidth;
        measuredMinHeight = measuredHeight = Math.max(textHeight, buttonHeight);
    }

Метод calculatePreferredSizeFromData, упомянутый @defmeta (реализован в mx.controls.ComboBox), предполагает, что средство визуализации данных является просто текстовым полем, и использует flash.text.lineMetrics для вычисления ширины текста из поля метки в объекте data. Если вы хотите добавить дополнительный визуальный элемент к средству визуализации элементов и иметь ComboBox, учитывающий его размер при расчете его собственного размера, вам придется расширить класс mx.controls.ComboBox и переопределить метод calculatePreferredSizeFromData следующим образом:

  override protected function calculatePreferredSizeFromData(count:int):Object
  {
      var prefSize:Object = super.calculatePrefferedSizeFromData(count);
      var maxW:Number = 0;
      var maxH:Number = 0;
      var bookmark:CursorBookmark = iterator ? iterator.bookmark : null;
      var more:Boolean = iterator != null;

      for ( var i:int = 0 ; i < count ; i++)
      {
          var data:Object;
          if (more) data = iterator ? iterator.current : null;
          else data = null;
          if(data)
          {
              var imgH:Number;
              var imgW:Number;

              //calculate the image height and width using the data object here

              maxH = Math.max(maxH, prefSize.height + imgH);
              maxW = Math.max(maxW, prefSize.width + imgW);
          }
          if(iterator) iterator.moveNext();
      }

      if(iterator) iterator.seek(bookmark, 0);
      return {width: maxW, height: maxH};
 }

Если возможно, сохраните размеры изображения в объекте данных и используйте эти значения как imgH и imgW, что значительно облегчит определение размера.

РЕДАКТИРОВАТЬ:

Если вы добавляете к элементу рендеринга помимо изображения, например метки, вам также придется вычислять их размер при выполнении итерации по элементам данных и учитывать эти измерения при расчете maxH и * 1024. *.

0 голосов
/ 16 сентября 2009

Вам нужно сделать две вещи:

  • для текста, используйте mx.controls.Text (который поддерживает перенос текста) вместо mx.controls.Label
  • set comboBox's dropdownFactory.variableRowHeight=true - этот dropdownFactory обычно является подклассом List, а itemRenderer, который вы устанавливаете в ComboBox, - это то, что будет использоваться для визуализации каждого элемента в списке

И, не устанавливайте явно comboBox.dropdownWidth - пусть значение по умолчанию comboBox.widt h будет использоваться в качестве ширины раскрывающегося списка.

0 голосов
/ 01 октября 2008

Этот ответ, вероятно, слишком поздно, но у меня была очень похожая проблема с шириной столбцов DataGrid.

После долгих попыток я решил предварительно отрендерить свой текст в частном TextField, получить из него ширину отрисованного текста и явно установить ширину столбца для всех соответствующих событий типа изменения размера. Немного хакерский, но работает достаточно хорошо, если у вас мало данных для изменения.

0 голосов
/ 19 сентября 2008

Вы пытались использовать метод CalculatePreferredSizeFromData () ?

protected override function calculatePreferredSizeFromData(count:int):Object
...