Spec-Zone.ru › Qt

Тип QML ViewTransition

Указывает элементы, находящиеся в процессе перехода в представлении. Подробнее...

Заявление об импорте: import QtQuick
  • Список всех членов, включая унаследованные

Присоединённые свойства

  • 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. Когда происходит пятая и последняя вставка, добавляя "Item 4" в представление, переход add выполняется один раз (для вставленного элемента), а переход displaced выполняется четыре раза (по одному для каждого из четырёх существующих элементов в представлении).

В этот момент, если мы изучим переход displaced , который был выполнен для перемещённого элемента снизу ("Item 0"), значения свойств ViewTransition, предоставленные этому переходу, будут следующими:

Свойство Значение Объяснение
ViewTransition.item экземпляр делегата "Item 0" Сам объект Rectangle "Item 0"
ViewTransition.index значение 4 в int Индекс "Item 0" в модели после операции добавления
ViewTransition.destination значение point (0, 120) Положение, в которое перемещается "Item 0"
ViewTransition.targetIndexes массив int, содержит только целое число "0" (ноль) Индекс "Item 4", нового элемента, добавленного в представление
ViewTransition.targetItems массив объектов, содержит только экземпляр делегата "Item 4" Объект Rectangle "Item 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 и проходит переход «добавления»; затем элемент 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 : точка

Это присоединенное свойство содержит конечную позицию перемещения элемента в представлении.

Значение этого свойства — точка со свойствами x и y.

ViewTransition.index : int

Это присоединенное свойство содержит индекс элемента, который переходит.

Обратите внимание, что если элемент перемещается, это свойство содержит индекс, в который перемещается элемент, а не из которого.

ViewTransition.item : элемент

Это присоединенное свойство содержит элемент, который переходит.

Предупреждение: Не следует хранить и ссылаться на этот элемент за пределами перехода, так как он может стать недопустимым при изменении представления.

ViewTransition.targetIndexes : список

Это присоединенное свойство содержит список индексов элементов в представлении, которые являются целевыми для соответствующей операции.

Целевые элементы — это элементы, которые являются объектом операции. Для операции добавления это элементы, которые добавляются; для удаления — это элементы, которые удаляются; для перемещения — это элементы, которые перемещаются.

Например, если переход был вызван операцией вставки, которая добавила два элемента в индекс 1 и 2, этот список targetIndexes будет иметь значение [1,2].

Примечание: Список targetIndexes содержит только индексы элементов, которые фактически находятся в представлении или будут в нем после завершения соответствующей операции.

См. также QtQuick::ViewTransition::targetItems.

ViewTransition.targetItems : список

Это присоединенное свойство содержит список элементов в представлении, которые являются целевыми для соответствующей операции.

Целевые элементы — это элементы, которые являются объектом операции. Для операции добавления это элементы, которые добавляются; для удаления — это элементы, которые удаляются; для перемещения — это элементы, которые перемещаются.

Например, если переход был вызван операцией вставки, которая добавила два элемента в индекс 1 и 2, этот список targetItems будет содержать эти два элемента.

Примечание: Список targetItems содержит только элементы, которые фактически находятся в представлении или будут в нем после завершения соответствующей операции.

Предупреждение: Объекты в этом списке не должны храниться и к ним не следует обращаться за пределами перехода, так как элементы могут стать недопустимыми. targetItems действительны только при первоначальном создании перехода; это также означает, что они не должны использоваться объектами ScriptAction в переходе, которые не вычисляются до запуска перехода.

См. также QtQuick::ViewTransition::targetIndexes.

END_OF_DOCUMENT_MARKER

© The Qt Company Ltd
Licensed under the GNU Free Documentation License, Version 1.3.
https://doc.qt.io/qt-6.2/qml-qtquick-viewtransition.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API