Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. QML and Qt Quick
  4. ListView that scrolls horizontally also
Forum Updated to NodeBB v4.3 + New Features

ListView that scrolls horizontally also

Scheduled Pinned Locked Moved Solved QML and Qt Quick
7 Posts 4 Posters 3.6k Views 4 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • SeeLookS Offline
    SeeLookS Offline
    SeeLook
    wrote on last edited by
    #1

    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

    1 Reply Last reply
    0
    • SeeLookS Offline
      SeeLookS Offline
      SeeLook
      wrote on last edited by
      #2

      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.

      T 1 Reply Last reply
      0
      • SeeLookS SeeLook

        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.

        T Offline
        T Offline
        Tom_H
        wrote on last edited by
        #3

        @SeeLook You could wrap it in a ScrollView.

        1 Reply Last reply
        1
        • Shrinidhi UpadhyayaS Offline
          Shrinidhi UpadhyayaS Offline
          Shrinidhi Upadhyaya
          wrote on last edited by Shrinidhi Upadhyaya
          #4

          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]

          Shrinidhi Upadhyaya.
          Upvote the answer(s) that helped you to solve the issue.

          1 Reply Last reply
          1
          • SeeLookS Offline
            SeeLookS Offline
            SeeLook
            wrote on last edited by
            #5

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

            1 Reply Last reply
            0
            • SeeLookS Offline
              SeeLookS Offline
              SeeLook
              wrote on last edited by
              #6

              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 }
                }
              }
              
              1 Reply Last reply
              0
              • R Offline
                R Offline
                returnx
                wrote on last edited by
                #7

                The clear way is use flickableDirection property.
                You can set flickableDirection to the Flickable.AutoFlickIfNeeded or Flickable.HorizontalAndVerticalFlick enums.

                1 Reply Last reply
                0

                • Login

                • Login or register to search.
                • First post
                  Last post
                0
                • Categories
                • Recent
                • Tags
                • Popular
                • Users
                • Groups
                • Search
                • Get Qt Extensions
                • Unsolved