13 Replies Latest reply on Nov 30, 2011 11:29 PM by Flex harUI

    renderer unscaledHeight in layoutContents

    eckhoff_randy Level 1

      I'm creating my own renderer and wonder where the value for unscaledHeight (and width) comes from when updateDisplayList is called that in turn calls layoutContents for LabelItemRenderer.

       

      I'm creating a grid item renderer (poor mans version of datagrid) for a mobile application. GridItemRenderer subclasses LabelItemRender. I've studied the code of LabelItemRenderer and IconItemRenderer and I think I understand the basics.

       

      I'm currently using a DataGroup but could just as easily be using a List and my experimentation with list yields the same information. Why are the individual rows so tall? I set the font size smaller hoping that the vertical space each renderer would take would get smaller but it doesn't and I don't understand why.

       

      In my measure() method, I've calculated the measuredHeight to be:

       

           var verticalPadding:Number = getStyle("paddingTop") + getStyle("paddingBottom");

           measuredHeight = getElementPreferredHeight(ld) + verticalPadding;

       

      With the fontsize set to 16, the measured height comes back as 12. The top and bottom padding I have set to 0.

       

      But when updateDisplayList is called which inturn calls layoutContents, unscaledHeight is set to 66. Even if the font size is set to 28, the unscaledHeight is set to 66. 66 is returned when I debug the application as an Andriod App (Droid 2) on the desktop. If I debug on an actual device like a Motorola Atrix, fontsize 16 yields a measuredHeight of 12 (just like the desktop debug) but the unscaledHeight is set to 44.

       

      I've tried setting the gap in the vertical layout to 0 within the datagroup but that didn't work.

       

      So how can I control that "row" height? What set of values is Flex looking at to come up with "66"?

       

      Thanks!

       

      Randy

        • 1. Re: renderer unscaledHeight in layoutContents
          Flex harUI Adobe Employee

          Try changing requestedRowCount

          • 2. Re: renderer unscaledHeight in layoutContents
            eckhoff_randy Level 1

            When I set requestedRowCount to the length of the list, the behavior remained the same.

             

            I put in a break point in another mobile application that is using a List and IconItemRenderer. The breakpoint was in IcontItemRender.layoutContents. The unscaledHeight and Width were set to 0 even though the measuredHeight was set to 74 when measure was called.

             

            So I'm really confused.

             

            Randy

            • 3. Re: renderer unscaledHeight in layoutContents
              Flex harUI Adobe Employee

              Assuming you are using VerticalLayout with useVirtualLayout, and the height of the list is as desired, the layout takes a renderer, asks it for its size, and keeps on going until it runs out of room.  Renderers have a “natural” size (height based on unconstrained width) and an “actual” size which is the size it will be based on the width allowed by the List.  It might be that the renderer isn’t reporting its height correctly given some width.  This is a common problem with wordwrapping text.

              • 4. Re: renderer unscaledHeight in layoutContents
                eckhoff_randy Level 1

                Yes, I am using verticalLayout. The height and width of the list is set to 100%. When you say "the layout takes a renderer, asks it for its size".... what method does it call to ask for the size? measure()? if it is the measure method, this is where I'm setting the actual measuredHeight and minimum Measured Height. The width is set to 480. I am not wrapping any text.

                 

                Where is the renderers natural size set?

                 

                Where is the actual size set?

                 

                If the renderer isn't reporting the height correctly given some width, where is the renderer supposed to calculate that? If it is all done in the measure method, the measure method is setting the height to 12 but the unscaled height coming into layoutContents is 66. Is the unscaledHeight supposed to match the height I set in the measure method? if not, where do i set the unscaledHeight?

                • 5. Re: renderer unscaledHeight in layoutContents
                  Flex harUI Adobe Employee

                  Do you have a simple test case we can look at?  The measure() method should get called although indirectly via getLayoutBoundsSize() and getPreferredBoundsWidth/Height().  If the width/height is getting set directly, that overrides measuredWidth/Height.

                  • 6. Re: renderer unscaledHeight in layoutContents
                    eckhoff_randy Level 1

                    Yes, I can send you the project. It is a small project and I modified the datagroup to take some test data so you don't have to enter data into a database. Let me know the best way to send it to you and i'll zip it up and send it.

                     

                    Further discoveries today:

                    I have 2 test cases. One is the small project I can send you. In it, i'm using a datagroup with a vertical layout. I tried setting the rowHeight to a small number along with variableRowHeight to true in hopes that that would affect the unscaledHeight coming into layoutContents. It did not. The test is most obvious when you modify the css to make the fontsize really small like 12 point.

                     

                    The other test case is much larger but rather simple. there I am using a regular spark list with width and height set to 100%. The item render I use is the spark iconitemrenderer where I have an icon, label and message. My first test here was to remove the icon so i just had the label and message. I made the fontsize for the label and message 12 point so the measuredHeight is now (without the icon) is 51. layoutContents still passes in 66 for the unscaledHeight. In this test, I did NOT have an explicit layout specified.

                     

                    So I tried having an explicit vertical layout specified within the s:List with variableRowHeight="true" rowHeight="51" gap="0". It didn't matter. I was hoping that the rowHeight attribute for verticallayout would override the unscaledHeight coming into layoutContents. It didn't.

                     

                    So for both datagroup with my custom renderer that subclasses LabelItemRender AND for a regular spark list with a regular spark iconitemrender, when i set the fontsize really small for both renderers, the height of that row remains rather large.

                     

                    More digging on the web pointed me to a website that said that the measure method was really just a "suggestion" to flex and that flex might override that suggestion? true? It sounds to me like Flex is saying "gee, that measuredHeight is awfully small, so we'll use this other value instead". OR i'm doing something totally wrong, even for the spark list and iconitemrenderer.

                     

                    Remember that this is for a mobile application so that might have something to do with it.

                     

                    Randy

                    • 7. Re: renderer unscaledHeight in layoutContents
                      Flex harUI Adobe Employee

                      Hopefully it is one file about 20 lines long and you can copy and paste it in here.

                      • 8. Re: renderer unscaledHeight in layoutContents
                        eckhoff_randy Level 1

                        here is the mxml:

                                                                                    
                             <s:Scroller width="100%" height="100%">
                                  <s:DataGroup id="detailsDataGroup" height="100%" width="100%"
                                             dataProvider="{heartData}" 
                                             styleName="detailsDataGroup"
                                             >
                                  <s:layout>
                                       <s:VerticalLayout useVirtualLayout="false" variableRowHeight="true" rowHeight="51" gap="0" />
                                  </s:layout>
                                  
                                  <s:itemRenderer> 
                                       <fx:Component>
                                            <renderers:GridItemRenderer>
                                            </renderers:GridItemRenderer>
                                       </fx:Component>
                                  </s:itemRenderer>
                             </s:DataGroup>
                             </s:Scroller>           
                                        
                                                                     
                                                           

                        Here is the measure method for my GridItemRenderer

                         

                                  override protected function measure():void
                                  {
                                       measuredMinWidth = 0;
                                       measuredMinHeight = 0;
                                       measuredWidth = 0;
                                       measuredHeight = 0;
                                       
                                       if (labelDisplayVector)
                                       {
                                            var horizontalPadding:Number = getStyle("paddingLeft") + getStyle("paddingRight");
                                            var verticalPadding:Number = getStyle("paddingTop") + getStyle("paddingBottom");
                        
                                            for (var i:int = 0; i < labelDisplayVector.length; i++) {
                                                 var ld:StyleableTextField = labelDisplayVector[i];
                                                 // reset text if it was truncated before.
                                                 if (ld.isTruncated)
                                                      ld.text = data[i];
                                                 // Text respects padding right, left, top, and bottom
                                                 ld.commitStyles();
                                                 measuredWidth += getElementPreferredWidth(ld) + horizontalPadding;
                                                 // We only care about the "real" ascent
                                                 measuredHeight = getElementPreferredHeight(ld) + verticalPadding; 
                                            }
                                            measuredWidth += (getStyle("horizontalGap") * (labelDisplayVector.length - 1));
                                            measuredWidth = parent.width;
                                       }               
                                       measuredMinWidth = measuredWidth;
                                       measuredMinHeight = measuredHeight;
                                       
                                       // in the list test, try setting the rowHeight of the verticalLayout to the measuredHeight. DIDN'T WORK.
                        //               var o:List = owner as List;
                        //               var l:VerticalLayout = o.layout as VerticalLayout;
                        //               l.rowHeight = measuredHeight;
                                  }
                                                           

                        here is the css for the itemrenderer.

                        .detailsDataGroup {
                             fontSize: 12;
                             horizontalGap:10;
                             paddingLeft:0;
                             paddingRight:0;
                             paddingTop:0;
                             paddingBottom:0;
                        }
                                                           
                        • 9. Re: renderer unscaledHeight in layoutContents
                          eckhoff_randy Level 1

                          Here is the s:list and iconitemrenderer code where the only thing i do is change the font size in the css. Nothing else is overridden. So even the spark provided components seem to be ignoring the measuredHeight value that gets set in measure() in IconItemRenderer:

                           

                               <s:List id="taskList" change="taskSelectionChanged(event)" height="100%" width="100%">
                                    <s:itemRenderer>
                                         <fx:Component> 
                                              <s:IconItemRenderer
                                                                       labelFunction="getLabel" messageFunction="getMessage">
                                                   <fx:Script> 
                                                        <![CDATA[ 
                          

                          here is the css:

                          .iconItemRendererMessageStyle {
                               fontSize: 12; /*20*/
                          }
                          
                           s|IconItemRenderer {
                               fontSize: 12;
                          }
                          
                          • 10. Re: renderer unscaledHeight in layoutContents
                            Flex harUI Adobe Employee

                            These are just snippets.  I want entire files I can copy, paste and run.

                            • 11. Re: renderer unscaledHeight in layoutContents
                              eckhoff_randy Level 1

                              Yup. I don't have just 1 file that is under 20 lines of code. According to the mobile doc, it is recommended to have the renderers as .as files, not within mxml for better performance. i'm certain you have an example s:list with an icon item renderer somewhere. just change the style to have a really small font size.

                              • 12. Re: renderer unscaledHeight in layoutContents
                                eckhoff_randy Level 1

                                I threw the following together using only spark components to hilight the issue. It is a mobile application. To reproduce, just debug the application on the desktop. I happen to use motorola droid 2 but the problem persists with other debug configurations. I'm using flex 4.5.1.

                                 

                                I don't know how else to more clearly describe the problem or how to more easily describe how to reproduce it. I await your explaination as to why the flex provided components seem to be ignoring the values in measure() or if it is working as designed, how one can override this behavior.

                                 

                                The below example shows 2 examples. The first example is a spark list using a spark iconitemrenderer. The 2nd example is using a spark datagroup using a spark labelitemrenderer. Just uncomment one and comment out the other to run the examples:

                                 

                                <?xml version="1.0" encoding="utf-8"?>
                                <s:View xmlns:fx="http://ns.adobe.com/mxml/2009" 
                                          xmlns:s="library://ns.adobe.com/flex/spark" 
                                          xmlns:mx="library://ns.adobe.com/flex/mx"
                                          title="HomeView">
                                     <fx:Declarations>
                                          <!-- Place non-visual elements (e.g., services, value objects) here -->
                                     </fx:Declarations>
                                     <fx:Style>          
                                          .iconItemRendererMessageStyle {
                                               fontSize: 12;
                                          }
                                                              
                                     </fx:Style>     
                                     
                                     <!-- EXAMPLE OF List with IconItemRenderer      -->
                                
                                <!--     
                                     <s:List id="taskList" height="100%" width="100%">
                                          <s:dataProvider>
                                               <mx:ArrayCollection>
                                                    <fx:String>one</fx:String> 
                                                    <fx:String>two</fx:String> 
                                                    <fx:String>three</fx:String> 
                                                    <fx:String>four</fx:String> 
                                               </mx:ArrayCollection>
                                          </s:dataProvider>          
                                          <s:itemRenderer> 
                                               <fx:Component> 
                                                    <s:IconItemRenderer labelFunction="getLabel" messageFunction="getMessage" fontSize="12"> 
                                                         <fx:Script> 
                                                              <![CDATA[ 
                                                                   private function getLabel(item:Object):String { 
                                                                        return "myLabel"; 
                                                                   } 
                                                                   
                                                                   private function getMessage(item:Object):String {
                                                                        return "myMessage";
                                                                   }
                                                              ]]> 
                                                         </fx:Script> 
                                                    </s:IconItemRenderer> 
                                               </fx:Component> 
                                          </s:itemRenderer> 
                                     </s:List>
                                -->     
                                     <!-- EXAMPLE OF DATAGROUP with LableItemRenderer -->
                                     
                                     <s:Scroller width="100%" height="100%">
                                          <s:DataGroup id="detailsDataGroup" height="100%" width="100%" >
                                               <s:layout>
                                                    <s:VerticalLayout useVirtualLayout="false" variableRowHeight="true" rowHeight="12" gap="0"/>
                                     <!--
                                          doesn't matter which vertical layout you use
                                                    
                                                    <s:VerticalLayout useVirtualLayout="false" variableRowHeight="false"/>
                                    -->                    
                                               </s:layout>
                                               <s:dataProvider>
                                                    <mx:ArrayCollection>
                                                         <fx:String>one</fx:String> 
                                                         <fx:String>two</fx:String> 
                                                         <fx:String>three</fx:String> 
                                                         <fx:String>four</fx:String> 
                                                    </mx:ArrayCollection>
                                               </s:dataProvider>          
                                               <s:itemRenderer> 
                                                    <fx:Component>
                                     
                                <!--
                                                         by setting the fontsize to 12 and padding to 0, when you put a break point in LableItemRenderer, the measure
                                                         method sets measured height to 9 (debugging on the desktop as a droid 2). measure is called 4 times.
                                                         layoutContents is called 8 times. twice for each record in array collection. The first time it is called for 
                                                         each array element, the unscaledHeight is 0. The 2nd time it is called for each array element,
                                                         the unscaledHeight is 66 even though the measuredHeight is set to 9.
                                -->
                                                         <s:LabelItemRenderer fontSize="12" paddingTop="0" paddingBottom="0"/>
                                                    </fx:Component>
                                               </s:itemRenderer>
                                          </s:DataGroup>
                                     </s:Scroller>     
                                     
                                </s:View>
                                
                                
                                • 13. Re: renderer unscaledHeight in layoutContents
                                  Flex harUI Adobe Employee

                                  Next time, use wiki markup around code snippets.  It looks like {-c-o-d-e-} without the dashes before and after the snippet.  In email, it came through escaped.

                                   

                                  I should’ve thought of this before, but the LabelItemRenderer sets a minHeight of 66 when DPI is 240.  Set it to something else if you need to.

                                   

                                  -Alex