11 Replies Latest reply on Jul 18, 2011 3:20 AM by Francisc

    Custome ItemRenderer - vertical center for label

    Francisc Level 3

      Hello,

       

      I am extending the LabelItemRender.

       

      I have a label called labelCategory.

      It is set to be multiline and to wordwrap.


      I am also overriding the layoutContents method and setting: labelCategory.y=(unscaledHeight-labelCategory.textHeight)/2;

       

      It works great when there is only one line of text.

      When there are two lines of text, it is off by 2 or 3 pixels.

       

      Maybe it's the maximum render height and it clips the label, not sure.

       

      In the measure override I am setting:

      measuredHeight=Math.max(labelDisplay.textHeight,labelCategory.textHeight)+TEXT_HEIGHT_PADD ING+10;

      TEXT_HEIGHT_PADDING is 4.

       

      How can I center the labelCategory vertically even when it's 2 lines?

       

      Thank you.

        • 1. Re: Custome ItemRenderer - vertical center for label
          Shongrunden Adobe Employee

          Can you post your LabelItemRenderer subclass?

          1 person found this helpful
          • 2. Re: Custome ItemRenderer - vertical center for label
            Francisc Level 3

            I don't have the latest version here, I'll post it later today.

             

            Had pasted an older version.

            • 3. Re: Custome ItemRenderer - vertical center for label
              Francisc Level 3

              Here it is. Very close to the one from the Flex docs.

               

              package renderers
              {
                  import spark.components.LabelItemRenderer;
                  import spark.components.supportClasses.StyleableTextField;

               

                  public class PlayerDetails extends LabelItemRenderer
                  {
                      public function PlayerDetails()
                      {
                          super();
                      }
                     
                      public var labelCategory:StyleableTextField;
                     
                      // Override createChildren() to create the StyleableTextField control control.
                      override protected function createChildren():void
                      {
                          super.createChildren();
                          labelDisplay.multiline=true;
                          labelDisplay.wordWrap=true;
                         
                          // Make sure it does not already exist.
                          if (!labelCategory)
                          {
                              labelCategory=new StyleableTextField();
                             
                              // Specify The object that provides styles for the control.
                              // This property must be set for the control to pick up the correct styles.
                              labelCategory.styleName=this;
                             
                              // Set basic attributes of the control.
                              labelCategory.editable=false;
                              labelCategory.selectable=false;
                              labelCategory.multiline=false;
                              labelCategory.wordWrap=false;
                             
                              // Add the control as a child of the item renderer.
                              addChild(labelCategory);
                          }
                      }
                     
                      // Override styleChanged() to proopgate style changes to labelTextField.
                      override public function styleChanged(styleName:String):void {
                          super.styleChanged(styleName);
                         
                          // Pass any style changes to labelTextField.
                          if(labelCategory)
                          {
                              labelCategory.styleChanged(styleName);
                          }
                      }
                     
                      // Override the data property to initialize labelTextField.
                      // The label function in the view specifies the String
                      // displayed in labelDisplay.
                      override public function set data(value:Object):void
                      {
                          super.data=value;
                          labelCategory.text=String(value.label);
                      }
                     
                      // Override measure() to calculate the size required by the item renderer.
                      override protected function measure():void {
                          super.measure();
                         
                          // Commit the styles changes to labelDisplay and labelTextField.
                          // This method must be called before the text is displayed,
                          // and any time the styles have changed.
                          // This method does nothing if the styles have already been committed.
                          labelDisplay.commitStyles();
                          labelCategory.commitStyles();
                         
                          // Becasue of the way the player calculates text widths and heights,
                          // define extra padding around the text to prevent clipping.
                          const TEXT_WIDTH_PADDING:int=5;
                          const TEXT_HEIGHT_PADDING:int=4;
                         
                          // Calculate the measured width and height of the item renderer,
                          // including text paddding.
                          // Include 6 pixels of extra space around the width, and 10 around
                          // the heiht of the item renderer.
                         
                          measuredWidth=labelDisplay.textWidth+labelCategory.textWidth+TEXT_WIDTH_PADDING+6;
                          measuredHeight=Math.max(labelDisplay.textHeight,labelCategory.textHeight)+TEXT_HEIGHT_PAD DING+10;
                         
                          // Set the minimum width and height of the item renderer.
                          measuredMinWidth=6;
                          measuredMinHeight=6;
                      }
                     
                      // Override layoutContents() to lay out the item renderer.
                      override protected function layoutContents(unscaledWidth:Number,unscaledHeight:Number):void {
                          // Because you are handling the layout of both the
                          // predefined labelDisplay component and the new
                          // labelTextField component, you do not have to call
                          // super.layoutContents().
                         
                          // Commit the styles changes to labelDisplay and labelTextField.
                          labelDisplay.commitStyles();
                          labelCategory.commitStyles();
                         
                          // Set the size and position of labelDisplay and labelTextField.
                          labelCategory.width=labelCategory.textWidth+5;
                          labelCategory.x=5;
                          labelCategory.y=(unscaledHeight-labelCategory.textHeight)/2;
                         
                          labelDisplay.width=unscaledWidth-(labelCategory.x+labelCategory.width)-5;
                          labelDisplay.x=labelCategory.x+labelCategory.width;
                          labelDisplay.y=(unscaledHeight-labelDisplay.textHeight)/2;
                      }
                  }
              }

              • 4. Re: Custome ItemRenderer - vertical center for label
                Shongrunden Adobe Employee

                Measuring and laying out multiline text can be tricky.  I would suggest looking at how IconItemRenderer does it for its messageField (check out layoutContents() and measure()).

                 

                Also it looks like you are the setting size and position of elements via the x/y/width/height properties, but you should be using setElementSize() and setElementPosition().  This will result in better performance by avoiding unnecessary layout passes (set the size before the position).  This is a best practice for ActionScript item renderers that inherit from the LabelItemRenderer class as well as ActionScript skins that inherit from the MobileSkin class.

                 

                Can you point me to the docs where you got this sample code from?

                • 5. Re: Custome ItemRenderer - vertical center for label
                  Francisc Level 3

                  Not sure how to say `Thank you.` that it doesn't look like a reflex.

                  • 6. Re: Custome ItemRenderer - vertical center for label
                    Francisc Level 3

                    Here's the link, couldn't find it right away.

                    http://help.adobe.com/en_US/flex/using/WS354da6572731dfda-28275bce12af7985b6f-8000.html

                     

                    It's here: public class MyGroupItemRenderer extends LabelItemRenderer

                    • 7. Re: Custome ItemRenderer - vertical center for label
                      Francisc Level 3

                      Steve: If I only want to set width for example, I can set height to NaN, right?

                      • 8. Re: Custome ItemRenderer - vertical center for label
                        Shongrunden Adobe Employee

                        Thanks for the pointer, I've filed a documentation bug: http://bugs.adobe.com/jira/browse/FLEXDOCS-1370

                         

                        I'm not sure I follow why you want to set the height to NaN, you don't want the height of the renderer to consider the height of the text field?

                        • 9. Re: Custome ItemRenderer - vertical center for label
                          Francisc Level 3

                          Hey!

                           

                          What I meant was when seting the size of an element, if I only want to set the width, leaving the height to be whatever it is that is default, how should this be done?

                           

                          For example, I have a text component I want be 100px wide, but keep it's default height. How would that look?

                          I remember reading that setting NaN is how it's done. Can't remember the source, I doubt it was a livedocs one.

                           

                          e.g. setElementSize(elem,100,NaN);

                          • 10. Re: Custome ItemRenderer - vertical center for label
                            Shongrunden Adobe Employee

                            I believe NaN is what you are looking for.  The setElementSize() method will typically call ILayoutElement.setLayoutBoundsSize().  According to the ASDoc for that method: "If the width and/or height parameters are left unspecified (NaN), Flex sets the element's layout size to its preferred width and/or preferred height."

                             

                            Has the text reflow code in IconItemRenderer been useful at all?  I've created a MultilineLabelItemRenderer class that applies the text reflow concept to the labelDisplay of a LabelItemRenderer.  Since it's much simpler than IconItemRenderer I'm hoping it will be a little easier to see how to accomplish this (see attached).

                            1 person found this helpful
                            • 11. Re: Custome ItemRenderer - vertical center for label
                              Francisc Level 3

                              I've changed the way I position elements so that I can avoid multiline actually. Haha.

                               

                              Thank you for the attached example, I hugely appreciate it. I'll try to learn as much as I can from it.