[QML] Changing layout between landscape and portrait mode

Is it possible to define 2 different layouts that the app will swicth between depending on phone orientation?

The documentation only mentions changing the layout/anchor locations based on isPortrait but if what if I say want to convert a Column into a Row or vice versa or change the hierarchy of elements?

You can’t make a Column become a Row, but you can use things like a Flow.

Something like:

    Flow {
      width: parent.width
      height: parent.height
      Column {
        width: (isLandscape) ? ( parent.width / 2)  : parent.width
      }
      Column {
        width: (isLandscape) ? ( parent.width / 2)  : parent.width
      }
    }

Or you could use a Loader to do completely different things depending on orientation.

    Component { id: portraitLayout
       Column { ... }
    }
    Component { id: landscapeLayout
       Row { ... }
    }
    Loader {
        sourceCompnent: isPortrait ? portraitLayout : landscapeLayout
    }

Or with something like a Grid and a Model, just set the rows/columns depending on orientation:

Grid {
    columns: isPortrait ?  1 : 3
    Repeater {
        model: whateverModel
        delegate: GridItem { ... }
    }
}
2 Likes

Thanks, I’m going to checkout both options for my usecase (I’m guessing that a Loader might produce a “hickup” in the userexperience), I had this vague memory that it was possible with some builtin property to define a landscape and a portrait layout maybe that is still from the n900/n9 days…

There’s also something called State in QML which I have seen used for portrait/landscape layout switching. Never used it myself though. Flow also works for some cases, that I have used.

2 Likes

This works;

import QtQuick 2.6
import Sailfish.Silica 1.0

Page {
    id: page

    allowedOrientations: Orientation.All

    SilicaFlickable {
        anchors.fill: parent

        Column {
            anchors.centerIn: parent
            visible: isPortrait ? true : false            
            Rectangle { width: 300; height: width; color: "red"
                Label { text: "Portrait"; anchors.centerIn: parent }
            }
        }
        Row {
            anchors.centerIn: parent
            visible: isLandscape ? true : false
            Rectangle { width: 300; height: width; color: "green"
                Label { text: "Landscape"; anchors.centerIn: parent }
            }
        }
    }
}
2 Likes

For now I used the Flow solution, will experiment with others, I think the “double” Row/Column solution with conditional visibility would not work for me because I have a VideoOutput of which you can only have one instance as far as I recall.

Is there a property that gives the absolute height/width of the screen? ie. height: screenHeight or somehing similar? (Or a list of builtin properties in SFOS)

1 Like

Do the properties of Screen do what you need?

1 Like