Тип QML ViewTransition
Определяет элементы, находящиеся в процессе перехода в представлении Подробнее...
| Заявление об импорте: | import QtQuick 2.5 |
Прикрепленные свойства
- 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. При выполнении пятой и последней вставки, добавляя "Item 4" в представление, переход add выполняется один раз (для вставленного элемента), а переход displaced выполняется четыре раза (по одному разу для каждого из четырех существующих элементов в представлении).
В этот момент, если мы изучим переход displaced, который был выполнен для смещенного снизу элемента ("Item 0"), значения свойства ViewTransition, предоставленные этому переходу, были бы следующими:
| Свойство | Значение | Описание |
|---|---|---|
| ViewTransition.item | экземпляр делегата "Item 0" | Сам объект "Item 0" Rectangle |
| ViewTransition.index | значение 4 для int |
Индекс "Item 0" в модели после операции добавления |
| ViewTransition.destination | значение точки (0, 120) | Позиция, в которую перемещается "Item 0" |
| ViewTransition.targetIndexes | массив, содержащий только целое число "0" (ноль) | Индекс "Item 4", нового элемента, добавленного в представление |
| ViewTransition.targetItems | массив объектов, содержащий только экземпляр делегата "Item 4" | Объект "Item 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].
END_OF_DOCUMENT_MARKERПримечание: Список 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/archives/qt-5.6/qml-qtquick-viewtransition.html