Моя головоломка, как правило, заключается в следующем: через какое-то действие вне GridView я хочу определить координаты конкретного элемента делегата в GridView, основываясь только на определенном элементе модели или индексе, выбранном ранее.
У меня есть GridView с рядом элементов в модели. Делегат GridView создает эскиз каждого элемента. При нажатии на нее открывается подробный полноэкранный вид элемента. Мне нужен приятный переход, который показывает, что миниатюра расширяется со своего места в GridView, и когда подробное представление отклоняется, сжимается обратно в GridView на месте.
Фокус в том, что подробный вид сам по себе является делегатом ListView, поэтому вы можете размещать страницы между подробными просмотрами по одному экрану за раз. Это означает, что решение, которое просто изменяет размер элемента делегирования GridView или что-то не будет работать. Кроме того, поскольку вы можете ссылаться на любой элемент в ListView, возврат к GridView должен выполняться только на основе информации, доступной в модели или индексе элемента модели (например, я не могу хранить координаты MouseArea, используемые для запуска подробный обзор или что-то еще).
Анимация расширения довольно проста, так как элемент делегата имеет MouseArea для обработчика кликов, который знает свое собственное размещение, поэтому его можно передать функции, запускающей анимацию. Это наоборот, я не могу понять: из элемента модели/индекса в ListView, как я могу определить координаты связанного элемента в GridView?
Я не могу найти что-либо в документах, которые, похоже, позволят вам получить доступ к экземпляру элемента делегата из экземпляра элемента модели или даже индекса. GridView имеет indexAt()
, который возвращает индекс, основанный на координатах. Я думаю, что я мог бы покончить с реверсом, но, похоже, он не существует.
Вот более конкретный пример. Извинения за длину; это самый короткий пример кода, который я мог бы придумать, чтобы точно описать мою проблему:
import QtQuick 1.1
Item {
id: window
width: 400
height: 200
state: "summary"
states: [
State { name: "summary"; },
State { name: "details"; }
]
transitions: [
Transition { from: "summary"; to: "details";
SequentialAnimation {
PropertyAction { target: animationRect; property: "visible"; value: true; }
ParallelAnimation {
NumberAnimation { target: animationRect; properties: "x,y"; to: 0; duration: 200; }
NumberAnimation { target: animationRect; property: "width"; to: 400; duration: 200; }
NumberAnimation { target: animationRect; property: "height"; to: 200; duration: 200; }
}
PropertyAction { target: detailsView; property: "visible"; value: true; }
PropertyAction { target: summaryView; property: "visible"; value: false; }
PropertyAction { target: animationRect; property: "visible"; value: false; }
}
},
Transition { from: "details"; to: "summary";
SequentialAnimation {
PropertyAction { target: summaryView; property: "visible"; value: true; }
// How to animate animationRect back down to the correct item?
PropertyAction { target: detailsView; property: "visible"; value: false; }
}
}
]
Rectangle {
id: animationRect
z: 1
color: "gray"
visible: false
function positionOverSummary(summaryRect) {
x = summaryRect.x; y = summaryRect.y;
width = summaryRect.width; height = summaryRect.height;
}
}
ListModel {
id: data
ListElement { summary: "Item 1"; description: "Lorem ipsum..."; }
ListElement { summary: "Item 2"; description: "Blah blah..."; }
ListElement { summary: "Item 3"; description: "Hurf burf..."; }
}
GridView {
id: summaryView
anchors.fill: parent
cellWidth: 100
cellHeight: 100
model: data
delegate: Rectangle {
color: "lightgray"
width: 95; height: 95;
Text { text: summary; }
MouseArea {
anchors.fill: parent
onClicked: {
var delegateRect = mapToItem(window, x, y);
delegateRect.width = width; delegateRect.height = height;
animationRect.positionOverSummary(delegateRect);
detailsView.positionViewAtIndex(index, ListView.Beginning);
window.state = "details";
}
}
}
}
ListView {
id: detailsView
anchors.fill: parent
visible: false
orientation: ListView.Horizontal
snapMode: ListView.SnapOneItem
model: data
delegate: Rectangle {
color: "gray"
width: 400; height: 200;
Column {
Text { text: summary; }
Text { text: description; }
}
MouseArea {
anchors.fill: parent
onClicked: {
// How do I get the coordinates to where animationRect should return?
summaryView.positionViewAtIndex(index, GridView.Visible);
window.state = "summary";
}
}
}
}
}
Любые идеи? Возможно, я просто ошибаюсь. Если то, что я пытаюсь сделать конкретно, невозможно, есть ли другой способ, которым я должен это делать? Спасибо!
Изменить: некоторые идеи, которые у меня были (ничто из того, что я считаю возможным):
-
Сохраните список всех созданных элементов делегата, используя
Component.onCompleted
иComponent.onDestruction
. Чтобы быть полезным, это должна быть карта элемента модели или индекса = > делегировать элемент. Проблема заключается в том, что основные типы документов (особенно variant) показывают, что этот вид карты невозможно создать в чистом QML. Таким образом, похоже, что это будет означать создание этой карты как класса С++ и использование этого в QML сonCompleted
/onDestruction
в компоненте делегата, чтобы поддерживать его в актуальном состоянии. Кажется немного опасным и тяжелым для чего-то, что должно быть просто. -
Этот список рассылки, кажется, указывает, что свойство Flickable
contentItem
может использоваться для перечисления элементов делегата. Затем я нашел этот пост, назвав это неправильной практикой. Я все еще смотрю в нее, но я скептически отношусь к этому, это будет законное решение. Кажется, слишком тяжело работать надежно.
Это все, что у меня есть.