Search code examples
androiddelphifiremonkeydelphi-10.1-berlin

Why won't controls span multiple columns or rows in an Android FireMonkey app?


I have a FireMonkey app with a GridPanelLayout, aligned to client. It's got 6 columns and 16 rows. Controls include glyphs, edits, and buttons. The TEdits span multiple columns, and the TButtons span both multiple columns and rows. The controls are currently all aligned to client.

When I compile and run on Windows everything looks and acts as expected. However, on Android devices (I tried two, Android 6.0.1, and Amazon FireOS) none of the controls span more than one column or row. They're each just one cell big. Instead of spanning 6 cols, TEdits span just 1 col; instead of spanning 2 cols and 2 rows, TButtons also span 1 col and 1 row.

Why won't the controls span multiple columns or rows on Android?


Solution

  • Both VCL and FireMonkey fail to store the ControlCollection of a TGridPanel / TGridPanelLayout correctly when a frame/form gets subclassed or a frame placed on another frame/form.

    This bug applies to both VCL and FMX. It has been reported to the old QC as early as 2011 but never been fixed (examples: #92298, #123225).

    Example: Drop a TGridPanelLayout with a TButton in it on a TFrame:

    object GridPanelLayout1: TGridPanelLayout
        (...)   
        ControlCollection = <
          item
            Column = 0
            ColumnSpan = 2
            Control = Button1
            Row = 0
            RowSpan = 2
          end>
        object Button1: TButton
          Align = Client
          Size.Width = 421.000000000000000000
          Size.Height = 257.000000000000000000
          Size.PlatformDefault = False
          TabOrder = 0
          Text = 'Button1'
        end
    end 
    

    When you later subclass the frame, the IDE tends to store a lot of redundant properties for the components it inherited from the base class. Usually after the first press of F9, the ColumnSpan and RowSpan properties get removed for no reason. On the subclass, it then looks something like this:

    inherited GridPanelLayout1: TGridPanelLayout
        (...)
        ControlCollection = <
            item
                Column = 0
                Control = Button1
                Row = 0
            end>
        inherited Button1: TButton
            Size.Width = 210.500000000000000000
            Size.Height = 128.500000000000000000
        end
    end
    

    Note how the Size property has changed. Also, the ControlCollection items get re-defined, yet the ColumnSpan and RowSpan properties are missing completely. This is the cause.

    This bug applies to you because in FMX, specialized views for specific platforms are implemented as subclasses of the master view.

    A version control system helps detecting when redundant properties sneak into DFM files. In the above example, it is legal to completely remove the inherited GridPanelLayout1 block when your subclass does not change it. Moreover, I advise you to build your project with no form designer window open as it often will corrupt your DFM file and re-add the redundant properties at every opportunity.