Search code examples
c++qtlistviewqml

QML, Keeping the position while zooming into a ListView


I am stuck on an issue regarding zooming into a ListView for multiple days now. I hope someone here might have a solution or an idea.

I have a ListView (with the id pageView) that has a model of images. The ListView has a property defaultPageHeight which indicates the default height of each image. It also has a zoomFactor property, that is default initialized to 1. The height of each delegate is set to:

height: Math.round(pageView.defaultPageHeight * pageView.zoomFactor)

I have overwritten the onWheel event of my ListView so that I can handle it manually. When I press CTRL+Scroll the zoom(factor) function is called, with a factor parameter that indicates how much to zoom.

The zooms function looks like this:

function zoom(factor)
{
    let newZoomFactor = pageView.zoomFactor * factor;
    let newPageHeight = Math.round(pageView.defaultPageHeight * newZoomFactor);
    
    // Make sure to store the position the listview was looking at before zooming
    let currentPageHeight = Math.round(pageView.defaultPageHeight * pageView.zoomFactor);
    let currentPageNumber = /*Gets the current page*/;
    let currentPos = pageView.contentY - pageView.originY;
    
    // Get the offset, meaning how far is the position away from the current page's top
    let pageOffset = currentPos - (currentPageHeight * currentPageNumber);
    
    // Apply the new zoom
    pageView.zoomFactor = newZoomFactor;

    // Set the new contentY
    pageView.contentY = newPageHeight * currentPageNumber + Math.round(pageOffset * newZoomFactor) + pageView.originY;
}

The zooming itself works fine, but I am not able to restore the position of the ListView before the zoom. So when I am zooming, I am also moving up or down in the listview for some reason.

You can see an example oft this in the following: https://imgur.com/a/cO4cAxq As you can see, the ListView is successfully zooming, but it is changing its position. I'd like it to zoom into the middle of the screen, instead of moving around the document while zooming.

I have set up a simple, minimal replica of this so that you can test it out locally. This is how it looks: https://imgur.com/a/acUmjjx You again see that it is zooming successfully, but moving across the ListView instead of zooming onto one point. Here is the code of the minimal replica: https://gist.github.com/DavidLazarescu/337d8b28e941cdbe6db3d4873ae45fd3

Thank you for any help in advance


Solution

  • It seems to have been a problem with originY. After recording some data of zooming I noticed that that setting pageView.zoomFactor = newZoomFactor; did not cause originY to refresh, so I was setting:

    pageView.contentY = newPageHeight * currentPageNumber + Math.round(pageOffset * newZoomFactor) + pageView.originY;
    

    while originY was the old originY and so I moved to a position that was originY away from where it should actually be. To refresh originY before I was calculating the new position, I needed to call pageView.forceLayout(); so that I can use the updated originY to calculate the actual position.

    EDIT: I have updated the gist to contain the fix.