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 :-)


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.