Jolla and SailfishOS
Horizontal Scrolling SilicaListViews
Some surprisingly tricky task I stumbled upon when developing D-Bus Inspector was how to get horizontal scrolling working for SilicaListViews, that have entries that are wider than the screen.
Standard Solution
Normally you would
- Assign the width of you widest element to
contentWidth
of theSilicaFlickable
- Add a
HorizontalScrollDecorator
IntrospectServicePage.qml
and you are done.
SilicaListView Solution
For a SilicaListView however this does not work (or at least I could not get it working).
Somehow the ListView is always as wide as the screen and hence the HorizontalScrollDecorator
is never shown.
To cut a long story short. What you have to do is
- Traverse through all your
Label
children of the list view (see Traversing the Label children) - Find the width of the widest
- Assign this width to
SilicaListView.implicitWidth
- Use
SilicaListView.implicitWidth
asSilicaFlickable.contentWidth
Traversing the Label children
This also turned out not to be as strait forward as it sounds.
- The
delegate
of theSilicaListView
adds aBackgroundItem
to it's list of children for each entry in the model found. - One of the children of every
BackgroundItem
added is aLabel
The problem traversing the children is, that there are also "hidden" children of unknown type.
So if you just try to access the width of every child element not only would you probably end up with the wrong value,
you might generate a runtime error since not all of the children have a width
property.
Here I had a little bit of help form the Internet. Unfortunately the link to the original post got lost somehow.
The basic idea is very elegant, because is simple:
- The article suggested to use a
typeId
property to identify the different elements we introduced.
So that is what we do:
- We introduce a new property
typeId
for each type of child we are interested in for one reason or another (lines 66 and 69 inDSessionBusServicesPage.qml
). - When traversing the child nodes, we ignore all children except the one bearing the correct
typeId
(lines 18 and 21 inGlobalFunctions.qml
). - At children level
Label
we implement a simple Max() routine and return the maximum value found when done.
Global Functions
Since I need to do this for a number of different instances of SilicaListView
, it makes sense to write a function that I can access from the global scope.
Turns out in QML this is strait forward.
It appears that if you use an identifier not known to QML in your code (as I did with GlobalFunctions
in line 15 of DSessionBusServicesPage.qml
),
QML uses a file of that name (+.qml
), if it can find one.
If you give that "import" an id
(line 16, same file), than you can access functions defined in that scope (file), as shown in line 57 of DSessionBusServicesPage.qml
.