[app] Workaround for positionViewAtIndex not working for the first time

This is probably a bug in QQuickListView - it first calculates the
item position and then starts instantiating the delegates. The very
first time the item position always turns out to be zero because the
average item size isn't known yet. So if we are trying to position the
list at a non-zero index and instead we got positioned at zero, try it
again.
This commit is contained in:
Slava Monich 2016-11-24 19:38:53 +02:00
parent 32013a8ac5
commit 77be4b68e8
2 changed files with 29 additions and 2 deletions

View file

@ -48,6 +48,7 @@ BooksListWatcher::BooksListWatcher(QObject* aParent) :
iListView(NULL), iListView(NULL),
iCenterMode(-1), iCenterMode(-1),
iPositionIsChanging(false), iPositionIsChanging(false),
iCanRetry(true),
iResizeTimer(new QTimer(this)) iResizeTimer(new QTimer(this))
{ {
iResizeTimer->setSingleShot(true); iResizeTimer->setSingleShot(true);
@ -62,6 +63,7 @@ void BooksListWatcher::setListView(QQuickItem* aView)
if (iListView) iListView->disconnect(this); if (iListView) iListView->disconnect(this);
iListView = aView; iListView = aView;
iCenterMode = -1; iCenterMode = -1;
iCanRetry = true;
if (iListView) { if (iListView) {
connect(iListView, connect(iListView,
SIGNAL(widthChanged()), SIGNAL(widthChanged()),
@ -139,13 +141,36 @@ void BooksListWatcher::positionViewAtIndex(int aIndex)
} }
} }
iPositionIsChanging = true; iPositionIsChanging = true;
QMetaObject::invokeMethod(iListView, LISTVIEW_POSITION_VIEW_AT_INDEX, positionViewAtIndex(aIndex, iCenterMode);
Q_ARG(int,aIndex), Q_ARG(int,iCenterMode)); if (iCanRetry) {
// This is probably a bug in QQuickListView - it first calculates
// the item position and then starts instantiating the delegates.
// The very first time the item position always turns out to be
// zero because the average item size isn't known yet. So if we
// are trying to position the list at a non-zero index and instead
// we got positioned at zero, try it again. It doesn't make sense
// to retry more than once though.
if (aIndex > 0 && getCurrentIndex() == 0) {
// Didn't work from the first try, give it another go
HDEBUG("retrying...");
positionViewAtIndex(aIndex, iCenterMode);
}
iCanRetry = false;
}
iPositionIsChanging = false; iPositionIsChanging = false;
updateCurrentIndex(); updateCurrentIndex();
} }
} }
void BooksListWatcher::positionViewAtIndex(int aIndex, int aMode)
{
if (iListView) {
QMetaObject::invokeMethod(iListView,
LISTVIEW_POSITION_VIEW_AT_INDEX,
Q_ARG(int,aIndex), Q_ARG(int,aMode));
}
}
qreal BooksListWatcher::contentX() qreal BooksListWatcher::contentX()
{ {
return getRealProperty(LISTVIEW_CONTENT_X); return getRealProperty(LISTVIEW_CONTENT_X);

View file

@ -66,6 +66,7 @@ private:
qreal contentY(); qreal contentY();
qreal getRealProperty(const char *name, qreal defaultValue = 0.0); qreal getRealProperty(const char *name, qreal defaultValue = 0.0);
int getCurrentIndex(); int getCurrentIndex();
void positionViewAtIndex(int aIndex, int aMode);
void updateCurrentIndex(); void updateCurrentIndex();
void updateSize(); void updateSize();
@ -92,6 +93,7 @@ private:
QQuickItem* iListView; QQuickItem* iListView;
int iCenterMode; int iCenterMode;
bool iPositionIsChanging; bool iPositionIsChanging;
bool iCanRetry;
QTimer* iResizeTimer; QTimer* iResizeTimer;
}; };