Spec-Zone.ru › Qt 6.1

Тип QML ViewTransition

Определяет элементы, участвующие в переходе в представлении. Подробнее...

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

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

  • 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 значение точки point (0, 120) Положение, в которое перемещается "Элемент 0"
ViewTransition.targetIndexes массив int, содержит только целое число "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 и проходит переход «добавление»; затем элемент 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 действительны только при первоначальном создании перехода; это также означает, что они не должны использоваться объектами ScriptAction в переходе, которые не вычисляются до выполнения перехода.

END_OF_DOCUMENT_MARKER

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

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

Spec-Zone.ru

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