Hidding an item outside viewport of a ListView
-
Hi,
This is my first topic here. I've been learning QtQuick for about a week and I'm facing a weird behaviour on what I'm trying to achieve. I would like to make a vertical ListView with a Keyboard navigation so that when I press UP or DOWN, the items move up or down and if an item goes out or in the "viewport", its opacity property will change smoothly to 0 or 1.
Here my QML code :
import QtQuick 2.4 Rectangle { width:200 height:400 ListView { property int activePosition:1 property int itemDisplayed:3 width:parent.width-50 height:parent.height-50 anchors.centerIn:parent model:10 snapMode:ListView.SnapToItem focus:true cacheBuffer:2000 Component.onCompleted: { console.log(count+' != '+contentItem.children.length+' ???') } Keys.onPressed: { var i = 0 console.log('pos='+activePosition) console.log(count+' != '+contentItem.children.length+' ???') if (event.key === Qt.Key_Up) { if (activePosition == 1 && currentIndex > 0) { i = currentIndex+itemDisplayed-1 if (i < contentItem.children.length - 2/* why -2 instead of -1 ??? */) { console.log('out='+i) contentItem.children[i].state = 'out' } } activePosition = activePosition > 1 ? activePosition - 1 : activePosition } if (event.key === Qt.Key_Down) { if (activePosition == itemDisplayed && currentIndex < contentItem.children.length - 2) { i = currentIndex-itemDisplayed+1 if (i >= 0) { console.log('out='+i) contentItem.children[i].state = 'out' } } activePosition = activePosition < itemDisplayed ? activePosition + 1 : activePosition } } delegate:Rectangle { id:rect state:index < ListView.view.itemDisplayed ? 'in' : 'out' opacity:1.0 width:ListView.view.width height:ListView.view.height/ListView.view.itemDisplayed border.color:'white' border.width:1 color:activeFocus ? 'red': 'gray' onActiveFocusChanged: { if (activeFocus) { state = 'in' console.log('in='+index) } } states: [ State { name:'in'; PropertyChanges { target:rect; opacity:1.0 } }, State { name:'out'; PropertyChanges { target:rect; opacity:0.0 } } ] transitions: [ Transition { to:'in' NumberAnimation { property:'opacity'; duration:250 } }, Transition { to:'out' NumberAnimation { property:'opacity'; duration:250 } } ] Text { text:index anchors.centerIn:parent } } } }
First question : model=10, why model.count is not equal to contentItem.children.length ? onCompleted gives 5 vs 11 and during navigation 10 vs 11
Second question:If I press UP or DOWN, it works fine until I reach index=4, why ?
As I'm a beginner on QtQuick so maybe it's not the right approch. I tried to use the "visible" property but every items have visible=true even if they are outside. I tried also indexAt() with no success.
Any help would be great :-)
-
set clip property to true.
-
Yes I can do that but I still want the items to disappear smoothly using opacity not to disappear at once :-)
-
I think the example shown in the ListView documentation for the "remove" property does what you want.
-
Not exactly because the remove property holds a transition which is triggered when an item is remove from the view and the model. In my case, the item is just out of the viewport but still in the model.
-
Delegates get deleted automatically when out of sight, which explains all the strange behavior you are experiencing. Try to play with property
cacheBuffer
. -
About my first question, I found the answer : contentItem.children.length contains 11 elements because there are 10 Rectangles (from the model) and the ListView itself.
Knowing that, I cannot rely on the contentItem.children's indexes vs. currentIndex because it won't match. That's why I'm having problem at index=4 because contentItem.children[4] is the ListView. By using the itemAt() method instead of indexAt(), I succeeded to achieve what I wanted :-)