Тип QML ViewTransition
Указывает элементы, находящиеся под переходом в представлении. Подробнее...
| Заявление об импорте: | import QtQuick 2.14 |
Присоединённые свойства
- 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" | Сам объект "Элемент 0" Rectangle |
| ViewTransition.index |
Значение 4 для int |
Индекс "Элемент 0" в модели после операции добавления |
| ViewTransition.destination | значение точки (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.14/qml-qtquick-viewtransition.html