Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

ListView that scrolls horizontally also



  • Hi,
    How to achieve such a thing?
    When I have delegate that its width is greater than available list width?
    Unfortunately only vertical scroll bar appears:

    ListView {
      id: list
      width: 300; height: 600
      model: 20
      delegate: Rectangle {
        width: list.width * 1.8; height: 100
        border { width: 1; color: "black"}
        Text {
          anchors.centerIn: parent
          text: (index + 1) + ". delegate"
        }
      }
    
      ScrollBar.vertical: ScrollBar { active: true; visible: true }
      ScrollBar.horizontal: ScrollBar { active: true; visible: true }
    }
    

    Screenshot_20191012_220044.png



  • ListView inherits from Flickable which is quite configurable for both scroll bars, but it seems like ListView locks horizontal bar, so I didn't find better solution than to 'cheat the system' :)
    and wrap ListView with Flickable and use its scrolls

    Column {
      width: 300; height: 600
      property real sc: 1.0
      Row {
        id: buttRow
        spacing: 10
        Button { icon.name: "zoom-in"; onClicked: sc = Math.min(2.0, sc * 1.125) }
        Button { icon.name: "zoom-out";  onClicked: sc = Math.max(0.5, sc * 0.888889) }
        Text { text: "Zoom: " + sc; anchors.verticalCenter: parent.verticalCenter }
      }
      Flickable {
        id: fl
        width: parent.width; height: parent.height - buttRow.height
        contentWidth: width * sc
        contentHeight: list.contentItem.height
        clip: true
        ListView {
          id: list
          width: fl.width * sc; height: parent.height
          model: 20
          delegate: Rectangle {
            width: list.width; height: 100
            border { width: 1; color: "black"}
            Text {
              anchors.centerIn: parent
              text: (index + 1) + ". delegate"
            }
          }
        }
        ScrollBar.horizontal: ScrollBar { active: true; visible: true }
        ScrollBar.vertical: ScrollBar { active: true; visible: true }
      }
    }
    

    Screenshot_20191013_140419.png

    This solution is quite bearable for me, but still, maybe there is something more elegant.



  • @SeeLook You could wrap it in a ScrollView.



  • Hi @SeeLook , you can use a ScrollView

    Here is a sample code:-

     ScrollView {
                width: 200
                height: 200
                clip: true
    
                ColumnLayout {
                    anchors.fill: parent
                    Repeater {
                        model: 10
                        delegate: Rectangle {
                            width: 400; height: 100
                            border { width: 1; color: "black"}
                            Text {
                                anchors.centerIn: parent
                                text: (index + 1) + ". delegate"
                            }
                        }
                    }
                }
            }
    

    Sample Output:-
    46beb47e-3a73-4304-a0a4-836854937223-image.png

    For more information about ScrollView[https://doc.qt.io/qt-5/qml-qtquick-controls2-scrollview.html]



  • @Tom_H , @Shrinidhi-Upadhyaya , Thanks for answers.
    Wrapping ListView by ScrollView is even mentioned in the Qt docs
    Let it be.
    Thank You.



  • Not that fast...
    It is not so clear as it looks like.

    As I wrote, Repeater is not sufficient due to number of delegates to be created.
    And for my purposes I decided to use the Flickable over the ScrollView (but it doesn't change a conclusion)
    Because when we set contentHeight: list.contentItem.height it resizes wrapping Flickable content item to size of our ListView content item, so the list have a space to create all one million delegates at once.
    No good...

    But below is the remedy: wrapping Flickable handles horizontal scrolling when inner ListView behaves its way, using only vertical scroll.

    Column {
      width: 300; height: 600
      property real sc: 1.0
      Row {
        id: buttRow
        spacing: 10
        Button { icon.name: "zoom-in"; onClicked: sc = Math.min(2.0, sc * 1.125) }
        Button { icon.name: "zoom-out";  onClicked: sc = Math.max(0.5, sc * 0.888889) }
        Text { text: "Zoom: " + sc; anchors.verticalCenter: parent.verticalCenter }
      }
      Flickable {
        id: fl
        width: parent.width; height: parent.height - buttRow.height
        contentWidth: width * sc
    //     contentHeight: list.contentItem.height // no good
        clip: true
        ListView {
          id: list
          width: fl.width * sc; height: parent.height
          model: 20
          delegate: Rectangle {
            width: list.width; height: 100 * sc
            border { width: 1; color: "black"}
            Text {
              anchors.centerIn: parent
              text: (index + 1) + ". delegate"
            }
          }
          ScrollBar.vertical: ScrollBar { active: true; visible: true }
        }
        ScrollBar.horizontal: ScrollBar { active: true; visible: true }
      }
    }
    

Log in to reply