ListItemLayout

ListItemLayout provides an easy way to create list items which follow Ubuntu design standards, thus making them visually appealing and consistent with the rest of the platform without effort. More...

Import Statement: import Ubuntu.Components 1.3
Since: Ubuntu.Components 1.3
Inherits:

SlotsLayout

Properties

Detailed Description

ListItemLayout is essentially a SlotsLayout with a predefined SlotsLayout::mainSlot that provides (up to) 3 Labels automatically laid out according to our UI guidelines. This main slot has been optimized to cover most of the usecases without compromising performance (read more in Optimizing memory consumption).

We're aware there could be usecases which the SlotsLayout::mainSlot provided by ListItemLayout doesn't cover. If that is the case, please use SlotsLayout instead of ListItemLayout and provide your own SlotsLayout::mainSlot.

ListItemLayout works similarly to QtQuick's Row, but while Row just positions its children in a horizontal formation, ListItemLayout also tweaks their vertical position to ensure a clean layout.

We will call ListItemLayout's visual children "slots". ListItemLayout positions its slots automatically, following the visual rules specified by the Ubuntu Design team. Because we think flexibility is an important value of our UI components, we made it possible to tweak the position of each slot by modifying its attached properties (see Advanced layout tweaks).

If you need a progression symbol in your list item, just add ProgressionSlot as a child of your ListItemLayout. No manual positioning is needed, the layout will handle it for you.

To read more about advanced slots positioning or how to handle input (mouse or touch) in ListItemLayout, see SlotsLayout documentation.

If you don't need the features provided by ListItem (such as the swiping actions), you can also use ListItemLayout directly as root of your list view delegate or inside a MouseArea, as explained in Input handling.

The following code example shows how easy it is to create even non trivial list items using ListItem and ListItemLayout:

ListItem {
    height: layout.height + (divider.visible ? divider.height : 0)
    ListItemLayout {
        id: layout
        title.text: "Hello developers!"
        subtitle.text: "I'm a subtitle, I'm tiny!"
        summary.text: "Ubuntu!"
        CheckBox { SlotsLayout.position: SlotsLayout.Leading }
        Icon {
            name: "message"
            SlotsLayout.position: SlotsLayout.Trailing;
            width: units.gu(2)
        }
    }
}

Although ListItemLayout covers most of the usecases, there might be times where you might want to tweak the position of one or more slots. The following example shows one way to implement a list item with a trailing slot holding two labels. What is special about this example is that we want the baseline of one label inside the trailing slot to align to title's baseline and the baseline of the other label to align to subtitle's baseline.

ListItem {
    id: listItem
    height: layout.height + (divider.visible ? divider.height : 0)
    ListItemLayout {
        id: layout
        title.text: "Hello..."
        title.color: UbuntuColors.Orange
        subtitle.text: "...world!"
        Rectangle {
            SlotsLayout.position: SlotsLayout.Leading
            color: "pink"
            height: units.gu(6)
            width: height
        }
        Item {
            id: slot
            width: secondLabel.width
            height: parent.height
            //as we want to position labels to align with title and subtitle
            SlotsLayout.overrideVerticalPositioning: true
            Label {
                id: firstLabel
                anchors.right: secondLabel.right
                text: "19:17"
                fontSize: "small"
                y: layout.mainSlot.y + layout.title.y
                   + layout.title.baselineOffset - baselineOffset
            }
            Label {
                id: secondLabel
                text: "Outgoing"
                fontSize: "small"
                y: layout.mainSlot.y + layout.subtitle.y
                   + layout.subtitle.baselineOffset - baselineOffset
            }
        }
    }
}

Labels layout

The labels in ListItemLayout's default SlotsLayout::mainSlot are laid out in a column. The title is positioned at the top, followed by subtitle and summary, respectively.

The subtitle has its top anchored to title's bottom, with a margin of 2 DPs.

The summary has its top tightly anchored to subtitle's bottom.

The height of the default SlotsLayout::mainSlot provided with ListItemLayout is the minimum height required to accomodate the visible and non-empty labels it holds. If only title is visible and has a non-empty text set, for instance, the height of the main slot will be title.height.

If you wish to have the layout process accomodate a label which doesn't have a defined text yet, you should set its text property to " ", as shown in the following example:

ListItemLayout {
    title.text: "Hello developers!"
    //NOTE: the whitespace
    subtitle.text: " "
}

That will make sure SlotsLayout::mainSlot is resized to accomodate the (currently empty) subtitle.

This is useful, for instance, if you want all list items in a list view to have the same height even without having to fill subtitle's (or summary's) text with dummy content.

Optimizing memory consumption

In order to minimize memory consumption, the Labels in the SlotsLayout::mainSlot are only allocated in memory on demand, i.e. the first time one of their properties is queried.

ListItemLayout {
    //NOTE: querying subtitle.text triggers allocation of subtitle Label
    Component.onCompleted: console.log(subtitle.text)
    title.text: "Hello developers!"
}

In the example above, querying subtitle.text will trigger the allocation in memory of the subtitle Label, which we don't actually use. We recommend avoiding querying properties of labels that we don't plan to use in the layout, in order to minimize memory consumption and maximize the scrolling performance of our list views.

ListItemLayout {
    //no extra labels created
    title.text: "Hello developers!"
}

About aliasing labels properties

Due to the way ListItemsLayout's labels are created (see Optimizing memory consumption) it is not possible to directly alias their properties. It is still possible, however, to expose an API that gives indirect read-write access to those properties. The following code:

ListItem {
    property alias titleText: layout.title.text
    ListItemLayout {
        id: layout
    }
}

will return the error "Invalid alias location", because the title object does not yet exist at time when the alias is created.

If you need to expose an API for your component that allows changing the properties of the labels, we recommend aliasing the labels themselves. Let's assume you want to create a QML component to use as a delegate of many list views inside your application: you will probably have a qml file holding the definition of the that delegate, and the content of that file will be similar to:

//Content of CustomListItem.qml
import QtQuick 2.4
import Ubuntu.Components 1.3
ListItem {
    id: listitem
    property alias title: layout.title
    property alias iconName: icon.name
    height: layout.height + (divider.visible ? divider.height : 0)
    ListItemLayout {
        id: layout
        Icon {
            id: icon
            width: units.gu(2)
        }
    }
}

As you can see, we alias the label item itself instead of its properties. This also has the advantage of only exposing one alias instead of one for each property, thus making your QML app a bit more performant. Once your delegate is defined, you can use it in your ListViews like usual.

//other UI code...
ListView {
    anchors.fill: parent
    model: ListModel {
        id: listViewModel
        ListElement { titleText: "Hello1"; icon: "message" }
        ListElement { titleText: "Hello2"; icon: "email" }
        ListElement { titleText: "Hello3"; icon: "email" }
        ListElement { titleText: "Hello4"; icon: "message" }
    }
    delegate: CustomListItem {
        title.text: model.titleText
        iconName: model.icon
    }
}

Note how title's properties are all accessible via the "title" identifier.

See also SlotsLayout and ProgressionSlot.

Property Documentation

subtitle : Label

This property defines the subtitle label and its properties. Styling and font properties can be set by using the prefix subtitle. in a similar way as shown in title.


summary : Label

This property defines the subtitle label and its properties. Styling and font properties can be set by using the prefix summary. in a similar way as shown in title.


title : Label

This property defines the title label and its properties. Styling and font properties can be set just like on any other Text component, as shown in the following example:

Item {
    ListItemLayout {
        title.text: "Hello"
        title.color: "yellow"
    }
}