Тип QML ViewTransition
Определяет элементы, находящиеся под переходом в представлении. Подробнее...
| Заявление об импорте: | import QtQuick 2.0 |
Присоединённые свойства
- destination : точка
- index : int
- 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" | Сам объект Rectangle "Элемент 0" |
| ViewTransition.index | значение 4 для int |
Индекс "Элемент 0" в модели после операции добавления |
| ViewTransition.destination | значение точки (0, 120) | Положение, в которое перемещается "Элемент 0" |
| ViewTransition.targetIndexes | массив, содержащий только целое число "0" (ноль) | Индекс "Элемент 4", нового элемента, добавленного в представление |
| ViewTransition.targetItems | массив объектов, содержащий только экземпляр делегата "Элемент 4" | Объект Rectangle "Элемент 4" - новый элемент, добавленный в представление |
Списки 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 и проходит переход "add"; затем элемент B вставляется в индекс 0 в быстрой последовательности, прежде чем переход элемента A завершится. Поскольку элемент B вставлен перед элементом A, он смещает элемент A, что заставляет представление прерывать переход "add" элемента A на полпути и вместо этого запускать переход "displaced" для элемента 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 изменяется на ссылку на другой элемент; элемент, на который script хотел сослаться, не является тем, который удерживается 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 содержит только элементы, которые фактически находятся в представлении или будут в представлении после завершения соответствующей операции.
Предупреждение: Объекты в этом списке не должны сохраняться и использоваться за пределами перехода, так как элементы могут стать недействительными. targetItems действительны только при первоначальном создании перехода; это также означает, что ими не должны пользоваться объекты ScriptAction в переходе, которые не вычисляются до запуска перехода.
См. также QtQuick::ViewTransition::targetIndexes.
© The Qt Company Ltd
Licensed under the GNU Free Documentation License, Version 1.3.
https://doc.qt.io/qt-6.0/qml-qtquick-viewtransition.html