Тип QML ViewTransition
Указывает элементы, находящиеся в процессе перехода в представлении. Подробнее...
| Заявление импорта: | import QtQuick 2.15 |
Прикрепленные свойства
- destination : точка
- index : целое число
- item : элемент
- targetIndexes : список
- targetItems : список
Подробное описание
С ListView и GridView можно указать переходы, которые должны применяться всякий раз, когда элементы в представлении изменяются в результате изменений модели представления. У обоих есть следующие свойства, которые можно установить для соответствующих переходов, которые должны выполняться для различных операций:
-
populate— переход, который нужно применить к элементам, первоначально созданным для представления, или при изменении модели -
add— переход, который нужно применить к элементам, добавленным в представление после его создания -
remove— переход, который нужно применить к элементам, удалённым из представления -
move— переход, который нужно применить к элементам, перемещённым внутри представления (т.е. в результате операции перемещения в модели) -
displaced— общий переход, который нужно применить к любым элементам, смещённым в результате добавления, перемещения или удаления -
addDisplaced,removeDisplacedиmoveDisplaced— переходы, которые нужно применить при смещении элементов в результате операций добавления, перемещения или удаления соответственно (эти переходы переопределяют общий переход при смещении, если он указан)
Для типов позиционеров Row, Column, Grid и Flow, которые работают со множествами дочерних элементов, а не с моделями данных, вместо этого используются следующие свойства:
-
populate— переход, который нужно применить к элементам, добавленным к позиционеру во время его создания -
add— переход, который нужно применить к элементам, добавленным к позиционеру или переданным в него, или к элементам, ставшими видимыми -
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» | Сам объект «Элемент 0» Rectangle |
| ViewTransition.index | значение 4 для int |
Индекс «Элемент 0» в модели после операции добавления |
| ViewTransition.destination | значение point (0, 120) | Позиция, в которую перемещается «Элемент 0» |
| ViewTransition.targetIndexes | массив int, содержит только целое число «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 : list
Это присоединённое свойство содержит список элементов в представлении, которые являются целевыми для соответствующей операции.
Цели — это элементы, которые являются объектом операции. Для операции добавления это элементы, которые добавляются; для удаления — элементы, которые удаляются; для перемещения — элементы, которые перемещаются.
Например, если переход был вызван операцией вставки, которая добавила два элемента в индексы 1 и 2, этот список targetItems будет содержать эти два элемента.
Примечание: список targetItems содержит только элементы, которые фактически находятся в представлении или будут в представлении после завершения соответствующей операции.
END_OF_DOCUMENT_MARKERПредупреждение: Объекты в этом списке не должны сохраняться и использоваться за пределами перехода, так как элементы могут стать недействительными. 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.15/qml-qtquick-viewtransition.html