positioning to the top of a listview after having incremented the size of a line



  • Hi,
    I have a technical issue about the ListView component.
    If I change the height of the items of a ListView, something wrong about the positioning to the top of the list can be observed.

    For example, a list of items with a height of 40 pixels.
    When we click over one of them, the height of the selected item is increased and the height of item selected before is decreased to 40 pixels
    When the height of an item is increased more than the visible height of the listview, then positioning to the top of the list becomes wrong.

    The problem is the same as we use the function positionViewAtIndex() or a calculation with listview.contentY to move to the top if the list.

    The problem can be bypassed by using listview.cacheBuffer.
    But I think this solution is not a good way because it uses more memory.

    has anybody an idea of the problem and how to solve it ?

    Thanks for your help

    Below, the exemple code

    import QtQuick 2.6
    import QtQuick.Window 2.2
    
    Window {
        property int        listContentHeight   : 0
        property int        collapsedLineHeight : 40
        property int        indexSel            : -1
    
        property bool       withFncPositionView : false
    
        visible: true
        width: 800
        height: 600
        title: qsTr("ListView Demo")
    
        Column {
            x:370
            y:200
            Text { text: "1 - Clic on the item 1, it expands and moves to the top of the list : OK" }
            Text { text: "2 - Clic on the item 2, it expands and moves to the top of the list : OK" }
            Text { text: "3 - Move to item 7 and clic on it, it expands and moves to the top of the list : OK" }
            Text { text: "4 - Scroll to item 8 and clic on it, it expands but the top of the list becomes wrong" }
            Text { text: " " }
            Text { text: "Problem is the same as we use the function positionViewAtIndex() or a calculation" }
            Text { text: "with listview.contentY to position the top if the list " }
        }
    
        ListModel {
            id : dataModel
            ListElement { selected: false; height: 80 ; color: "red"    }
            ListElement { selected: false; height: 120; color: "green"  }
            ListElement { selected: false; height: 70 ; color: "blue"   }
            ListElement { selected: false; height: 90 ; color: "yellow" }
            ListElement { selected: false; height: 130; color: "purple" }
            ListElement { selected: false; height: 100; color: "pink"   }
            ListElement { selected: false; height: 80 ; color: "orange" }
            ListElement { selected: false; height: 554; color: "brown"  }
    
            ListElement { selected: false; height: 80 ; color: "red"    }
            ListElement { selected: false; height: 120; color: "green"  }
            ListElement { selected: false; height: 70 ; color: "blue"   }
            ListElement { selected: false; height: 90 ; color: "yellow" }
            ListElement { selected: false; height: 130; color: "purple" }
            ListElement { selected: false; height: 100; color: "pink"   }
            ListElement { selected: false; height: 80 ; color: "orange" }
            ListElement { selected: false; height: 554; color: "brown"  }
    
        }
    
        Rectangle {
            x: 100
            y: 200
            width: 200
            height: 200
            color: "#400000FF"
    
            ListView {
                id                 : view
                anchors.fill       : parent
                anchors.leftMargin : 20
                anchors.rightMargin: 20
                focus              : true
                model              : dataModel
                contentWidth       : width
    
                // with cacheBuffer contentY and positionViewAtIndex run well, but this solution increases the memory use
                // cacheBuffer        : 900
    
                // this animation doesn't work
                // Behavior on contentY {NumberAnimation{duration: 200}}
    
                // this animation works
                NumberAnimation { id: moveViewAnimation; target: view; property: "contentY"; duration: 200 }
    
                delegate: Rectangle {
                    anchors { left: parent.left; right: parent.right }
                    color   : model.color
                    opacity : 0.6
                    height  : model.selected? model.height:collapsedLineHeight
                    Text {anchors.leftMargin:20; text:model.index}
                    MouseArea{
                        anchors.fill: parent
                        onClicked: {
                            // collapses item previously expanded
                            collapse(index)
                            // expands this item and positions view on it
                            model.selected = !model.selected
                            if(model.selected) {
                                moveViewAtIndex(index)
                                indexSel = index
                            }
                            updateContentHeight()
                        }
                    }
                }
            }
        }
    
    
        function collapse(index)
        {
            for(var i=0; i < view.model.count; i++) {
                var object = view.model.get(i)
                if( object.selected && i!== index ) {
                    object.selected = false
                    break
                }
            }
            indexSel = -1
        }
    
        function moveViewAtIndex(indexToGo)
        {
            if(indexToGo === -1)
                return
    
            if( withFncPositionView ) {
                view.positionViewAtIndex(indexToGo, ListView.Beginning)
            }
            else {
                moveViewAnimation.stop()
                var yNew = view.originY + collapsedLineHeight*indexToGo
                moveViewAnimation.to = yNew
                moveViewAnimation.start()
            }
        }
    
        function updateContentHeight() {
            listContentHeight = 0
            for(var i=0; i < view.model.count; i++) {
                var object = view.model.get(i)
                listContentHeight += object.selected? object.height : 40
            }
        }
    
    }
    
    

Log in to reply