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. Can't get my ListView Scrollbehavior correct in my simple example
Forum Updated to NodeBB v4.3 + New Features

Can't get my ListView Scrollbehavior correct in my simple example

Scheduled Pinned Locked Moved Unsolved QML and Qt Quick
2 Posts 1 Posters 766 Views
  • 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.
  • L Offline
    L Offline
    LowLevelM
    wrote on last edited by LowLevelM
    #1

    cross-posted from: https://stackoverflow.com/questions/57079018/qml-cant-get-my-listview-scrollbehavior-correct-in-my-simple-example

    Its my first time to use ListView and i need to implement a decent scroll behavior for my application
    it "works" but sometimes the animation behavior is a little bit strange

    I've wrote a small QML example (runnable with qmlscene tool) to show my problem

    alt text

    Sample source code:

    import QtQuick 2.2
    import QtQuick.Window 2.5
    
    Window {
        width: 500
        height: 700
        visible: true
    
        // my model ctrl is in C++
        // faked it here with pure QML to simplify the example
        ListModel {
            id: cppModel
            // different size - item type depdendend (just const here)
            ListElement { name: "Item 1"; active: false; height: 50 }
            ListElement { name: "Item 2"; active: false; height: 100 }
            ListElement { name: "Item 3"; active: false; height: 150 }
            ListElement { name: "Item 4"; active: false; height: 200 }
            ListElement { name: "Item 5"; active: false; height: 250 }
            ListElement { name: "Item 6"; active: false; height: 300 }
    
            property int currentItemIndex: -1
    
            function activate_item(index) {
                // auto deactivate all others
                for(var i = 0; i < rowCount(); i++) {
                    var active = (index === i)
                    get(i).active = active
                    if(active) {
                        currentItemIndex = i
                    }
                }
            }
        }
    
        Component {
            id: listViewDelegate
    
            Rectangle
            {
                height: model.active ? model.height : 30
                width: 600
                color: "transparent"
                border {color: model.active ? "yellow" : "black"; width: 2}
    
                Behavior on height {
                    NumberAnimation {
                        easing.type: Easing.InCirc
                        duration: 5000
                    }
                }
    
                Text {
                    text: model.name;
                    font.pixelSize: 24
                }
    
                MouseArea {
                    anchors.fill: parent
                    onClicked: {
                        cppModel.activate_item(model.index)
                    }
                }
            }
        }
    
        Rectangle
        {
            width: 400
            height: 600
            border {color: "steelblue"; width: 2}
    
            ListView {
                id: myList
                anchors.fill: parent
                clip: true
                model: cppModel
                delegate: listViewDelegate
    
                header: Rectangle {
                    width: parent.width; height: 50
                    border {color: "red"; width: 2}
                    Text {
                        anchors.centerIn: parent
                        text: "Header"
                        font.pixelSize: 32
                    }
                }
    
                highlightMoveDuration: 5000
                highlightMoveVelocity: -1
                highlightResizeDuration: 5000
                highlightResizeVelocity: -1
    
                preferredHighlightBegin: 0
                preferredHighlightEnd: currentItem.height
                highlightRangeMode: ListView.StrictlyEnforceRange
    
                snapMode: ListView.SnapToItem
    
                currentIndex: -1
    
                onMovementStarted: {
                    // show header again
                    highlightRangeMode = ListView.ApplyRange
                }
                onCurrentIndexChanged: {
                    // highlight current
                    highlightRangeMode = ListView.StrictlyEnforceRange
                }
            }
    
            Connections {
                target: cppModel
                onCurrentItemIndexChanged: { // change comming from C++
                    if ( myList.currentIndex !== cppModel.currentItemIndex ) {
                        myList.currentIndex = cppModel.currentItemIndex
                    }
                }
            }
        }
    }
    

    first: the item that is activated should be scrolled to top (that works) seems ok, only the animation i get are a little strange

    my 2 "bad" animation scenarios:

    if you activate Item 1..6 downwards, starting with Item 3 the Item Text is moved too far up and then comes back, the up scrolling should always stop at the items top, no bouncing etc. - i've already tried to replace the highlighter but gives me no better result

    if you open for example Item 6 and the scroll with mouse to Item 1 and activates item 1, the animation (seems to) first closes the Item 6 and then scrolls the list, better would be that the scrolling/and resize to the activated item 1 is prio and the closing animation of the former item does not block/stutter the item 1 animation

    would be glad if someone could kick me in the right direction how to solve the animation problems

    thanks

    1 Reply Last reply
    0
    • L Offline
      L Offline
      LowLevelM
      wrote on last edited by LowLevelM
      #2

      a played a while with the ListView options but can't get the animations right
      so i've tried to implement my own list view like item - as an example how the animation would feel

      working sample, with an fake c++ model, with the animations i want to see

      import QtQuick 2.5
      import QtQuick.Controls 2.5
      import QtQuick.Window 2.5
      
      Window {
          width: 500
          height: 700
          visible: true
      
          // my model ctrl is in C++
          // faked it here with pure QML to simplify the example
          ListModel {
              id: cppModel
              // different size - item type depdendend (just const here)
              ListElement { name: "Item 1"; active: false; height: 100 }
              ListElement { name: "Item 2"; active: false; height: 150 }
              ListElement { name: "Item 3"; active: false; height: 200 }
              ListElement { name: "Item 4"; active: false; height: 250 }
              ListElement { name: "Item 5"; active: false; height: 300 }
              ListElement { name: "Item 6"; active: false; height: 350 }
      
              property int currentItemIndex: -1
      
              function activate_item(index) {
                  // auto deactivate all others
                  for(var i = 0; i < rowCount(); i++) {
                      var active = (index === i)
                      get(i).active = active
                      if(active) {
                          currentItemIndex = i
                      }
                  }
              }
      
              function remove_item(index) {
                  if(currentItemIndex === -1) {
                      console.log("can remove not active item")
                      return
                  }
      
                  remove(currentItemIndex);
              }
      
              function deactivate_current_item()
              {
                  if(currentItemIndex === -1) {
                      console.log("can remove not active item")
                      return
                  }
                  get(currentItemIndex).active = false
              }
          }
      
          Column {
      
              Rectangle {
                  width: 320
                  height: 480
      
                  border { width: 2; color: "steelblue" }
      
                  Flickable {
                      id: flickable
                      clip: true
                      anchors.fill: parent
                      contentWidth: 320
                      contentHeight: 600
      
                      function goto_header()
                      {
                          contentY = 0
                      }
      
                      Behavior on contentY {
                          NumberAnimation {
                              easing.type: Easing.OutCubic
                              duration: 500
                          }
                      }
      
                      Rectangle {
                          id: myList
      
                          anchors.top: parent.top
                          anchors.left: parent.left
                          width: flickable.contentWidth
                          height: flickable.contentHeight
      
                          Column {
                              Rectangle {
                                  id: header
                                  width: 320
                                  height: 40
                                  color: "red"
                                  border { width: 2; color: "black" }
                                  Text { text: "Header"}
                              }
      
                              Repeater {
                                  model: cppModel
                                  Rectangle {
                                      readonly property int reducedSize: 30
                                      width: 320
                                      height: model.active ? model.height : reducedSize
                                      border { width: 2; color: "black" }
                                      Text {
                                          text: model.name
                                      }
      
                                      MouseArea {
                                          anchors.fill: parent
                                          onClicked: {
                                              // find new list contentY
                                              // works also if item above is shrinking
                                              // but only if shrinked height is for all items the same
                                              var newContentY = (model.index * reducedSize) + header.height
      
                                              cppModel.activate_item(model.index)
      
                                              // scroll to this element
                                              flickable.contentY = newContentY
                                          }
                                      }
      
                                      Behavior on height {
                                          NumberAnimation {
                                              easing.type: Easing.OutCubic
                                              duration: 500
                                          }
                                      }
                                  }
                              }
                          }
                      }
                  }
              }
      
              Rectangle {
                  height: 100
                  width: 320
      
                  Row
                  {
                      Button {
                          text: "Delete"
                          onClicked: {
                              console.log("Delete clicked")
                              cppModel.remove_item();
                              flickable.goto_header();
                          }
                      }
                      Button {
                          text: "Save"
                          onClicked: {
                              console.log("Save clicked")
                              cppModel.deactivate_current_item()
                          }
                      }
                  }
              }
          }
      }
      
      

      Screenshot of the sample program

      0_1563517642889_Screenshot from 2019-07-19 08-27-03.png

      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