Тип QML ViewTransition
Определяет элементы, участвующие в переходе в представлении Подробнее...
| Заявление об импорте: | import QtQuick 2.7 |
Присоединённые свойства
- 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 для индекса "Элемент 0" в модели после операции добавления | Индекс "Элемент 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 содержит только индексы элементов, которые фактически находятся в представлении или будут находиться в представлении после завершения соответствующей операции.
END_OF_DOCUMENT_MARKERСм. также 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.9/qml-qtquick-viewtransition.html