Тип QML ViewTransition
Указывает элементы, находящиеся под переходом в представлении. Подробнее...
| Заявление об импорте: | import QtQuick 2.13 |
Присоединенные свойства
- destination : point
- index : int
- item : item
- targetIndexes : list
- targetItems : list
Подробное описание
С ListView и GridView можно указать переходы, которые должны применяться всякий раз, когда элементы в представлении изменяются в результате модификаций модели представления. У них оба есть следующие свойства, которые можно установить для соответствующих переходов, которые необходимо выполнить для различных операций:
-
populate- переход, который необходимо применить к элементам, первоначально созданным для представления, или когда модель изменяется -
add- переход, который необходимо применить к элементам, добавленным в представление после его создания -
remove- переход, который необходимо применить к элементам, удаленным из представления -
move- переход, который необходимо применить к элементам, перемещенным внутри представления (т. е. в результате операции перемещения в модели) -
displaced- общий переход, который необходимо применить к любым элементам, смещенным из-за добавления, перемещения или удаления -
addDisplaced,removeDisplacedиmoveDisplaced- переходы, которые должны применяться при смещении элементов из-за операций добавления, перемещения или удаления соответственно (эти переходы переопределяют общий переход при смещении, если он указан)
Для типов позиционеров Row, Column, Grid и Flow, которые работают с наборами дочерних элементов, а не с моделями данных, вместо этого используются следующие свойства:
-
populate- переход, который необходимо применить к элементам, добавленным к позиционеру во время его создания -
add- переход, который необходимо применить к элементам, добавленным в позиционер или перемещенным в него, или элементам, ставшими видимыми visible -
move- переход, который необходимо применить к элементам, перемещенным внутри позиционера, включая случай, когда они смещаются из-за добавления или удаления других элементов, или когда элементы иначе переупорядочиваются внутри позиционера, или когда элементы перемещаются из-за изменения размера других элементов в позиционере
Переходы представления имеют доступ к присоединенному свойству ViewTransition, которое предоставляет подробности о элементах, находящихся под переходом, и операции, которая спровоцировала переход. Поскольку переходы представления выполняются один раз на элемент, эти сведения могут использоваться для настройки каждого перехода для каждого отдельного элемента.
Присоединенное свойство ViewTransition предоставляет следующие свойства, специфичные для элемента, к которому применяется переход:
- ViewTransition.item - элемент, находящийся под переходом
- ViewTransition.index - индекс этого элемента
- ViewTransition.destination - точка (x, y), в которую этот элемент перемещается для соответствующей операции представления
Кроме того, ViewTransition предоставляет свойства, специфичные для элементов, являющихся целевыми для операции, спровоцировавшей переход:
- ViewTransition.targetIndexes - индексы целевых элементов
- ViewTransition.targetItems - сами целевые элементы
(Обратите внимание, что для типов позиционеров Row, Column, Grid и Flow переход move предоставляет эти две дополнительные детали только при активации перехода добавлением элементов в позиционер.)
Переходы представления могут быть написаны без ссылки на любые из перечисленных выше атрибутов. Эти атрибуты просто предоставляют дополнительные сведения, полезные для настройки переходов представления.
Ниже представлено введение в переходы представления и способы использования присоединенного свойства ViewTransition для дополнения переходов представления.
Переходы представления: простой пример
Вот базовый пример использования переходов представления. Представление ниже указывает переходы для свойств add и displaced, которые будут выполняться при добавлении элементов в представление:
ListView {
width: 240; height: 320
model: ListModel {}
delegate: Rectangle {
width: 100; height: 30
border.width: 1
color: "lightsteelblue"
Text {
anchors.centerIn: parent
text: name
}
}
add: Transition {
NumberAnimation { property: "opacity"; from: 0; to: 1.0; duration: 400 }
NumberAnimation { property: "scale"; from: 0; to: 1.0; duration: 400 }
}
displaced: Transition {
NumberAnimation { properties: "x,y"; duration: 400; easing.type: Easing.OutBounce }
}
focus: true
Keys.onSpacePressed: model.insert(0, { "name": "Item " + model.count })
} При нажатии клавиши пробела, добавляющей элемент в модель, новый элемент будет появляться с эффектом затухания и увеличения масштаба в течение 400 миллисекунд по мере добавления его в представление. Кроме того, любой элемент, смещенный добавлением нового элемента, будет анимирован до своего нового положения в представлении в течение 400 миллисекунд, как указано в переходе displaced.
Если пять элементов будут вставлены последовательно в индекс 0, эффект будет следующим:
Обратите внимание, что объекты NumberAnimation выше не нуждаются в указании target для анимации соответствующего элемента. Кроме того, NumberAnimation в addTransition не нужно указывать значение to для перемещения элемента в правильное положение в представлении. Это связано с тем, что представление неявно устанавливает значения target и to с правильными значениями элемента и конечного положения элемента, если эти свойства не определены явно.
В самом простом случае переход представления может просто анимировать элемент в его новое положение после операции представления, как и переход displaced выше, или анимировать некоторые свойства элемента, как в переходе add выше. Кроме того, переход представления может использовать присоединенное свойство ViewTransition для настройки поведения анимации для различных элементов. Ниже приведены примеры того, как это можно сделать.
Использование присоединенного свойства ViewTransition
Как указано, различные свойства ViewTransition предоставляют сведения, специфичные для отдельного анимируемого элемента, а также операции, которая спровоцировала переход. На анимации выше пять элементов вставлены последовательно в индекс 0. Когда происходит пятая и последняя вставка, добавляется «Элемент 4» в представление, переход add выполняется один раз (для вставленного элемента), а переход displaced выполняется четыре раза (по одному разу для каждого из четырех существующих элементов в представлении).
В этот момент, если бы мы изучили переход displaced который был выполнен для смещенного нижнего элемента («Элемент 0»), значения свойства ViewTransition, предоставленные этому переходу, были бы следующими:
| Свойство | Значение | Описание |
|---|---|---|
| ViewTransition.item | экземпляр делегата "Элемент 0" | Сам объект Rectangle "Элемент 0" |
| ViewTransition.index | значение 4 | Индекс "Элемент 0" в модели после операции добавления |
| ViewTransition.destination | значение point (0, 120) | Позиция, в которую перемещается "Элемент 0" |
| ViewTransition.targetIndexes | массив, содержащий только целое число «0» (ноль) | Индекс «Элемент 4», нового элемента, добавленного в представление |
| ViewTransition.targetItems | массив объектов, содержащий только экземпляр делегата «Элемент 4» | Объект «Элемент 4» Rectangle - новый элемент, добавленный в представление |
Списки ViewTransition.targetIndexes и ViewTransition.targetItems предоставляют элементы и индексы всех экземпляров делегатов, являющихся целевыми для соответствующей операции. Для операции добавления это все элементы, которые добавляются в представление; для удаления — все элементы, удаленные из представления, и так далее. (Обратите внимание, что эти списки будут содержать только ссылки на элементы, созданные внутри представления или в кэше элементов; целевые элементы, которые не находятся в области видимости представления или в кэше элементов, недоступны.)
Таким образом, в то время как значения ViewTransition.item, ViewTransition.index и ViewTransition.destination различаются для каждого отдельного выполняемого перехода, значения ViewTransition.targetIndexes и ViewTransition.targetItems одинаковы для каждого перехода add и displaced , который вызывается определенной операцией добавления.
Задержка анимаций на основе индекса
Поскольку каждая перестройка представления выполняется один раз для каждого элемента, затронутого перестройкой, свойства ViewTransition могут использоваться в рамках перестройки для определения пользовательского поведения для перестройки каждого элемента. Например, ListView в предыдущем примере мог бы использовать эту информацию для создания эффекта волнообразного движения смещенных элементов.
Этого можно достичь, модифицировав перестройку displaced, так что она задерживает анимацию каждого смещенного элемента, основываясь на разнице между его индексом (предоставленным ViewTransition.index) и индексом первого удаленного элемента (предоставленным ViewTransition.targetIndexes):
displaced: Transition {
id: dispTrans
SequentialAnimation {
PauseAnimation {
duration: (dispTrans.ViewTransition.index -
dispTrans.ViewTransition.targetIndexes[0]) * 100
}
NumberAnimation { properties: "x,y"; duration: 400; easing.type: Easing.OutBounce }
}
} Каждый смещенный элемент задерживает свою анимацию на дополнительные 100 миллисекунд, создавая едва заметный эффект волнообразного движения при перемещении элементов, как в этом примере:
Анимирование элементов до промежуточных позиций
Свойство ViewTransition.item предоставляет ссылку на элемент, к которому применяется перестройка. Это можно использовать для доступа к любым атрибутам элемента, пользовательским property значениям и так далее.
Ниже приведена модификация перестройки displaced из предыдущего примера. Она добавляет ParallelAnimation с вложенными объектами NumberAnimation, которые ссылаются на ViewTransition.item для доступа к значениям x и y каждого элемента в начале их перестроек. Это позволяет каждому элементу анимироваться до промежуточной позиции относительно начальной точки перестройки, прежде чем анимироваться до конечной позиции в представлении:
displaced: Transition {
id: dispTrans
SequentialAnimation {
PauseAnimation {
duration: (dispTrans.ViewTransition.index -
dispTrans.ViewTransition.targetIndexes[0]) * 100
}
ParallelAnimation {
NumberAnimation {
property: "x"; to: dispTrans.ViewTransition.item.x + 20
easing.type: Easing.OutQuad
}
NumberAnimation {
property: "y"; to: dispTrans.ViewTransition.item.y + 50
easing.type: Easing.OutQuad
}
}
NumberAnimation { properties: "x,y"; duration: 500; easing.type: Easing.OutBounce }
}
} Теперь смещенный элемент сначала переместится в позицию (20, 50) относительно своей начальной позиции, а затем в свою конечную, правильную позицию в представлении:
Поскольку конечный NumberAnimation не указывает значение to, представление неявно устанавливает это значение в конечную позицию элемента в представлении, и поэтому эта последняя анимация переместит этот элемент в нужное место. Если для перестройки требуется конечная позиция элемента для какого-либо вычисления, она доступна через ViewTransition.destination.
Вместо использования нескольких NumberAnimations можно использовать PathAnimation для анимирования элемента по кривой. Например, перестройка add в предыдущем примере может быть дополнена PathAnimation следующим образом: для анимирования вновь добавленных элементов по пути:
add: Transition {
id: addTrans
NumberAnimation { property: "opacity"; from: 0; to: 1.0; duration: 400 }
NumberAnimation { property: "scale"; from: 0; to: 1.0; duration: 400 }
PathAnimation {
duration: 1000
path: Path {
startX: addTrans.ViewTransition.destination.x + 200
startY: addTrans.ViewTransition.destination.y + 200
PathCurve { relativeX: -100; relativeY: -50 }
PathCurve { relativeX: 50; relativeY: -150 }
PathCurve {
x: addTrans.ViewTransition.destination.x
y: addTrans.ViewTransition.destination.y
}
}
}
} Это анимирует вновь добавленные элементы по пути. Обратите внимание, что каждый путь задаётся относительно конечной точки назначения каждого элемента, так что элементы, вставленные в разные индексы, начинают свои пути с разных позиций:
Обработка прерванных анимаций
Перестройка представления может быть прервана в любой момент, если необходимо применить другую перестройку представления, пока исходная перестройка находится в процессе. Например, предположим, что элемент A вставляется в индекс 0 и проходит перестройку "добавления"; затем элемент B вставляется в индекс 0 быстро, прежде чем перестройка элемента A завершится. Поскольку элемент B вставляется перед элементом A, он смещает элемент A, заставляя представление прервать перестройку "добавления" элемента A на полпути и вместо этого начать перестройку "смещения" для элемента A.
Для простых анимаций, которые просто анимируют перемещение элемента в конечную точку назначения, эта прерывистость вряд ли потребует дополнительного рассмотрения. Однако, если перестройка изменяет другие свойства, это прерывание может вызвать нежелательные побочные эффекты. Рассмотрим первый пример на этой странице, повторенный ниже для удобства:
ListView {
width: 240; height: 320
model: ListModel {}
delegate: Rectangle {
width: 100; height: 30
border.width: 1
color: "lightsteelblue"
Text {
anchors.centerIn: parent
text: name
}
}
add: Transition {
NumberAnimation { property: "opacity"; from: 0; to: 1.0; duration: 400 }
NumberAnimation { property: "scale"; from: 0; to: 1.0; duration: 400 }
}
displaced: Transition {
NumberAnimation { properties: "x,y"; duration: 400; easing.type: Easing.OutBounce }
}
focus: true
Keys.onSpacePressed: model.insert(0, { "name": "Item " + model.count })
} Если несколько элементов добавляются в быстрой последовательности, не дожидаясь завершения предыдущей перестройки, результат будет таким:
Каждый вновь добавленный элемент проходит перестройку add, но прежде чем перестройка может завершиться, добавляется другой элемент, смещая ранее добавленный элемент. Из-за этого перестройка add на ранее добавленном элементе прерывается, и вместо этого запускается перестройка displaced для этого элемента. Из-за прерывания анимации opacity и scale не завершены, в результате чего элементы имеют непрозрачность и масштаб меньше 1.0.
Для исправления этого, перестройка displaced должна дополнительно гарантировать, что свойства элемента установлены в конечные значения, указанные в перестройке add, эффективно сбрасывая эти значения всякий раз, когда элемент смещается. В данном случае это означает установку непрозрачности и масштаба элемента в 1.0:
displaced: Transition {
NumberAnimation { properties: "x,y"; duration: 400; easing.type: Easing.OutBounce }
// ensure opacity and scale values return to 1.0
NumberAnimation { property: "opacity"; to: 1.0 }
NumberAnimation { property: "scale"; to: 1.0 }
} Теперь, когда перестройка add элемента прерывается, его непрозрачность и масштаб анимируются до 1.0 при смещении, что предотвращает нежелательные визуальные эффекты, которые были раньше:
Тот же принцип применим к любой комбинации перестроек представления. Добавляемый элемент может быть перемещен, прежде чем закончится его перестройка добавления, или перемещаемый элемент может быть удален, прежде чем закончится его перестройка перемещения, и так далее; поэтому, общее правило заключается в том, что каждая перестройка должна обрабатывать тот же набор свойств.
Ограничения, связанные с ScriptAction
Когда перестройка представления инициируется, любые привязки свойств, которые ссылаются на присоединённое свойство ViewTransition, оцениваются в подготовке к перестройке. Из-за особенностей внутренней реализации перестройки представления, атрибуты присоединённого свойства ViewTransition действительны только для соответствующего элемента при инициировании перестройки и могут не быть действительными, когда перестройка фактически выполняется.
Поэтому ScriptAction в рамках перестройки представления не должен ссылаться на присоединённое свойство ViewTransition, так как он может не ссылаться на ожидаемые значения в момент фактического вызова ScriptAction. Рассмотрим следующий пример:
ListView {
width: 240; height: 320
model: ListModel {
Component.onCompleted: {
for (var i=0; i<8; i++)
append({"name": i})
}
}
delegate: Rectangle {
width: 100; height: 30
border.width: 1
color: "lightsteelblue"
Text {
anchors.centerIn: parent
text: name
}
objectName: name
}
move: Transition {
id: moveTrans
SequentialAnimation {
ColorAnimation { property: "color"; to: "yellow"; duration: 400 }
NumberAnimation { properties: "x,y"; duration: 800; easing.type: Easing.OutBack }
ScriptAction { script: moveTrans.ViewTransition.item.color = "lightsteelblue" }
}
}
displaced: Transition {
NumberAnimation { properties: "x,y"; duration: 400; easing.type: Easing.OutBounce }
}
focus: true
Keys.onSpacePressed: model.move(5, 1, 3)
} При нажатии клавиши пробела три элемента перемещаются из индекса 5 в индекс 1. Для каждого перемещенного элемента последовательность moveTransition предположительно анимирует цвет элемента в "жёлтый", затем анимирует его в конечную позицию, а затем изменяет цвет элемента обратно в "lightsteelblue" с помощью ScriptAction. Однако при запуске перестройка не даёт ожидаемого результата:
Только последний перемещённый элемент возвращён к цвету "lightsteelblue"; остальные остаются жёлтыми. Это происходит потому, что ScriptAction не выполняется до тех пор, пока перестройка не будет инициализирована, к тому времени значение ViewTransition.item изменяется на ссылку на другой элемент; элемент, на который скрипт намеревался сослаться, не является элементом, удерживаемым ViewTransition.item в момент фактического вызова ScriptAction.
В данном случае, чтобы избежать этой проблемы, представление могло бы установить свойство с помощью PropertyAction вместо этого:
move: Transition {
id: moveTrans
SequentialAnimation {
ColorAnimation { property: "color"; to: "yellow"; duration: 400 }
NumberAnimation { properties: "x,y"; duration: 800; easing.type: Easing.OutBack }
//ScriptAction { script: moveTrans.ViewTransition.item.color = "lightsteelblue" } BAD!
PropertyAction { property: "color"; value: "lightsteelblue" }
}
} При инициализации перестройки PropertyAction target будет установлен на соответствующий ViewTransition.item для перестройки и позднее будет выполнен с правильной целью элемента, как ожидалось.
Документация по присоединённым свойствам
ViewTransition.destination : point
Это присоединённое свойство содержит конечную позицию перемещения элемента в представлении.
Это значение свойства представляет собой point со свойствами x и y.
ViewTransition.index : int
Это присоединённое свойство содержит индекс элемента, который перестраивается.
Обратите внимание, что если элемент перемещается, это свойство содержит индекс, в который перемещается элемент, а не от которого.
ViewTransition.item : item
Это присоединённое свойство содержит элемент, который перестраивается.
Предупреждение: Этот элемент не следует сохранять и использовать вне перестройки, так как он может стать недействительным при изменении представления.
ViewTransition.targetIndexes : list
Это присоединённое свойство содержит список индексов элементов в представлении, являющихся целью соответствующей операции.
Цели — это элементы, являющиеся объектом операции. Для операции добавления это добавляемые элементы; для удаления — удаляемые элементы; для перемещения — перемещаемые элементы.
Например, если переход был вызван операцией вставки, которая добавила два элемента по индексам 1 и 2, этот список targetIndexes будет содержать значение [1,2].
Примечание: Список targetIndexes содержит только индексы элементов, которые фактически находятся в представлении или будут в представлении после завершения соответствующей операции.
См. также QtQuick::ViewTransition::targetItems.
ViewTransition.targetItems : список
Это присоединённое свойство хранит список элементов в представлении, являющихся целью соответствующей операции.
Цели — это элементы, которые являются предметом операции. Для операции добавления это добавляемые элементы; для удаления — удаляемые элементы; для перемещения — перемещаемые элементы.
Например, если переход был вызван операцией вставки, которая добавила два элемента по индексам 1 и 2, этот список targetItems будет содержать эти два элемента.
Примечание: Список targetItems содержит только элементы, которые фактически находятся в представлении или будут в представлении после завершения соответствующей операции.
Предупреждение: Объекты в этом списке не должны сохраняться и использоваться за пределами перехода, так как элементы могут стать недействительными. targetItems действительны только при первоначальном создании перехода; это также означает, что их не следует использовать объектами ScriptAction в переходе, которые вычисляются только при выполнении перехода.
См. также QtQuick::ViewTransition::targetIndexes.
© The Qt Company Ltd
Licensed under the GNU Free Documentation License, Version 1.3.
https://doc.qt.io/qt-5.13/qml-qtquick-viewtransition.html