4

I'm creating a QML layout with a Column and multiple Rows inside. First row contains a button, second row contains a list of items retrieved from a network service. I want to be able to do "pull to refresh" on the list, so I use PullToRefresh of the ListView.

However, this adds the visible string "Pull to refresh..." to the top of the row output, actually appearing near the top of the first row. This kind of makes sense, except that I want that text to be hidden under the first row until it slides out when the list in the 2nd row is pulled.

Here's the minimum QML to reproduce, which can be run with qmlscene:

import QtQuick 2.4
import QtQuick.XmlListModel 2.0
import Ubuntu.Components 1.3

MainView {

    id: root
    width: units.gu(50)
    height: units.gu(75)

    Column {
        Row {
            Button {
                id: selector
                text: "Select"
            }
        }
        Row {
            ListView {
                id: listOfThings
                height: 500
                width: 400
                model: things
                delegate: Text {
                    text: title + " (" + pubDate + ")"
                }
                PullToRefresh {
                    refreshing: things.status === XmlListModel.Loading
                    onRefresh: things.reload()
                }
            }
        }
    }

    XmlListModel {
        id: things
        source: "https://news.yahoo.com/rss/"
        query: "/rss/channel/item"
        XmlRole { name: "title"; query: "title/string()" }
        XmlRole { name: "pubDate"; query: "pubDate/string()" }
    }
}

I cannot get the "Pull to refresh..." string to hide under the first row. Things I've tried so far that didn't work:

  • set z values, higher value for first row, lower for the 2nd: no effect
  • enclosing the button in the first row inside a Rectangle: the rectangle doesn't auto-stretch to fit the button and row dimensions collapse to 0
  • placing a white Rectangle in the first row, to the right of the button: this has been the most promising, but it's quite a hack
  • setting a background of a row: didn't find how that was possible

This must be a common use case, but I can't find any answers/examples. How do I hide the "Pull to refresh..." string under the row above it, until it is pulled into the row below? Or, are Column and Rows not the right components to use when doing this?

Unix One
  • 1,151
  • 7
  • 14

2 Answers2

3

Try adding this line:

        ListView {
            id: listOfThings
            clip: true   // <- this line! 
            height: 500
            width: 400
mardy
  • 164
  • 6
  • Excellent, this is exactly what I was looking for - thank you! I wish docs had a way to point out commonly used/needed properties like this one. – Unix One Oct 05 '16 at 16:04
1

One thing you could try is to use the ListView's header delegate for your "refresh" UI

Kevin Krammer
  • 5,159
  • 2
  • 9
  • 22
  • Hi Kevin, could you please elaborate how I'd use the `header` delegate to accomplish "pull to refresh" behavior? I'm not able to find any examples for that either. Would you mind sharing some code? – Unix One Oct 03 '16 at 15:20
  • The `header` delegate is an item that is part of the scrollable content of a list view but positioned before the first actual content item. Same goes for the `footer` at the end. Either of these will appear once the view has been scrolled far enough to the respective end. My suggestion is to try using the `header` item, e.g. whether it is visible or not, where it is relative to the beginning of the view, to trigger your refresh – Kevin Krammer Oct 08 '16 at 15:35
  • Hi Kevin, thank you for the clarification. As I understand, that would mean re-implementing what `PullToRefresh {...}` already does. But I'll keep this in mind in case I want to customize how header and footer look. – Unix One Oct 11 '16 at 06:39