Тип QML StackView
Предоставляет модель навигации на основе стека. Подробнее...
| Заявление об импорте: | import QtQuick.Controls 1.4 |
| С момента: | Qt 5.1 |
| Наследует: |
Свойства
- busy : bool
- currentItem : Item
- delegate : StackViewDelegate
- depth : int
- initialItem : var
Методы
- void clear()
- void completeTransition()
- Item find(function, bool onlySearchLoadedItems)
- Item get(int index, bool dontLoad)
- Item pop(Item item)
- Item push(Item item)
Подробное описание
StackView реализует модель навигации на основе стека, которая может быть использована с набором взаимосвязанных страниц информации. Элементы помещаются в стек по мере того, как пользователь углубляется в материал, и извлекаются обратно, когда он выбирает возврат.
Пример галереи касаний — хорошая отправная точка для понимания работы StackView. Следующий фрагмент кода из примера показывает, как его можно использовать:
StackView {
id: stack
initialItem: view
Component {
id: view
MouseArea {
Text {
text: stack.depth
anchors.centerIn: parent
}
onClicked: stack.push(view)
}
}
} Использование StackView в приложении
Использование StackView в приложении обычно сводится к добавлению StackView в качестве дочернего элемента Window. Стек обычно привязывается к краям окна, за исключением верхней или нижней части, где он может быть привязан к строке состояния или другому аналогичному UI-компоненту. Затем стек можно использовать, вызывая его методы навигации. Первый элемент, отображаемый в StackView, — это тот, который был назначен свойству initialItem.
Примечание: Элементы, помещенные в стек просмотра, имеют присоединенные свойства стека.
Основная навигация
Существует три основных операции навигации в StackView: push(), pop() и замена (замена путем указания аргумента replace для push()). Они соответствуют классическим операциям стека, где «push» добавляет элемент в верхнюю часть стека, «pop» удаляет верхний элемент из стека, а «замена» похожа на «pop», за которым следует «push», поскольку она заменяет верхний элемент стека новым элементом (но применённая анимация перехода может быть другой). Верхний элемент стека соответствует элементу, который в данный момент виден на экране. Это означает, что «push» логически эквивалентен навигации вперёд или глубже в приложение, «pop» — возврату назад, а «замена» — замене текущего элемента.
Иногда необходимо вернуться назад более чем на один шаг в стеке, например, вернуться к главному элементу или какому-то разделу приложения. Для этого случая можно указать элемент в качестве параметра для pop(). Это называется операцией «разворачивания», поскольку стек разворачивается до указанного элемента. Если элемент не найден, стек разворачивается до тех пор, пока в нём не останется только один элемент, который затем становится текущим элементом. Чтобы явно развернуться до нижней части стека, рекомендуется использовать pop(null), хотя технически любой несуществующий элемент подойдёт.
Учитывая стек [A, B, C]:
- push(D) => [A, B, C, D] - анимация перехода «push» между C и D
- pop() => [A, B] - анимация перехода «pop» между C и B
- push(D, replace) => [A, B, D] - анимация перехода «замена» между C и D
- pop(A) => [A] - анимация перехода «pop» между C и A
Примечание: Когда стек пуст, push() не выполнит анимацию перехода, потому что нет ничего, с чем можно перейти (обычно во время запуска приложения). pop() в стеке с глубиной 1 или 0 — это операция бездействия. Если необходимо удалить все элементы из стека, доступна отдельная функция clear().
Вызов push() возвращает элемент, который был помещён в стек. Вызов pop() возвращает элемент, который был извлечён из стека. При вызове pop() в операции развёртывания возвращается самый верхний элемент (первый элемент, который был извлечён, который также будет элементом, который выполняет переход).
Глубокие ссылки
Глубокая ссылка означает запуск приложения в определённом состоянии. Например, приложение газеты можно запустить так, чтобы оно отображало определённую статью, минуя начальный элемент (и, возможно, элемент раздела), через который обычно приходится проходить для доступа к интересующей статье. В терминах StackView глубокая ссылка означает способность изменять состояние стека, настолько, что можно поместить набор элементов в верхнюю часть стека или полностью сбросить стек до заданного состояния.
API для глубоких ссылок в StackView такое же, как и для основной навигации. Если в качестве аргумента передать массив, а не один элемент, то все элементы этого массива будут помещены в стек. Анимация перехода, однако, будет выполняться так, как будто в стек был помещён только последний элемент массива. Стандартные семантика push() применимы к глубоким ссылкам, что означает, что push() добавляет всё, что помещено в стек. Обратите также внимание, что загружается только последний элемент массива. Остальные будут загружаться по мере необходимости при входе на экран при последующих вызовах pop (или при запросе элемента с помощью get).
Это даёт нам следующий результат, учитывая стек [A, B, C]:
- push([D, E, F]) => [A, B, C, D, E, F] - анимация перехода «push» между C и F
- push([D, E, F], replace) => [A, B, D, E, F] - анимация перехода «замена» между C и F
- clear(); push([D, E, F]) => [D, E, F] - анимация перехода отсутствует (поскольку стек был пустым)
Помещение элементов
Элемент, помещённый в StackView, может быть элементом Item, URL, строкой, содержащей URL, или компонентом. Для его размещения назначьте его свойству «item» в списке свойств и передайте его в качестве аргумента для push:
stackView.push({item: yourItem}) Список может содержать несколько свойств, которые управляют тем, как элемент должен быть помещён:
-
item: это обязательное свойство, содержащее элемент, который необходимо поместить. -
properties: список свойств QML, которые необходимо назначить элементу при помещении. Эти свойства будут скопированы в элемент при загрузке или когда элемент станет текущим элементом (обычно при помещении). -
immediate: установите это свойство вtrueдля пропуска эффектов перехода. При помещении массива это свойство нужно установить только для первого элемента, чтобы сделать всю операцию мгновенной. -
replace: установите это свойство для замены текущего элемента в стеке. При помещении массива вам нужно установить это свойство только для первого элемента, чтобы заменить столько элементов в стеке, сколько элементов внутри массива. -
destroyOnPop: установите этот булево значение вtrueесли StackView необходимо уничтожить элемент, когда он извлекается из стека. По умолчанию (если destroyOnPop не указано), StackView уничтожит элементы, помещённые в виде компонентов или URL. Элементы, которые не уничтожаются, будут возвращены к их исходным родительским элементам, которые у них были до помещения в стек, и скрыты. Если вам нужно установить это свойство, делайте это осторожно, чтобы избежать утечек элементов.
Если единственным необходимым аргументом является «item», можно использовать следующее сокращённое обозначение:
stackView.push(yourItem)
Можно поместить несколько элементов сразу, используя массив списков свойств. Это более эффективно, чем помещать элементы по одному, так как StackView может загрузить только последний элемент в списке. Остальные будут загружены, когда они собираются стать текущим элементом (что происходит при извлечении из стека). Следующий пример показывает, как поместить массив элементов:
stackView.push([{item: yourItem1}, {item: yourItem2}]) Если помещается внутренний элемент, этот элемент временно переносится в родительский элемент StackView. Позже, когда элемент извлекается, он возвращается обратно в своего исходного владельца. Однако, если элемент помещается как компонент или URL, фактический элемент будет создан как элемент из этого компонента. Это происходит автоматически, когда элемент собирается стать текущим элементом в стеке. Владение элементом обычно переходит к StackView, который автоматически уничтожит этот элемент, когда он позже извлекается. Компонент, который объявил этот элемент, по-прежнему принадлежит приложению и не уничтожается стеком. Это можно изменить, явно установив destroyOnPop в списке аргументов, передаваемых в push.
Если properties для помещения указаны, они будут скопированы в элемент во время загрузки (в случае компонента или URL) или когда элемент станет текущим элементом (в случае внутреннего элемента). Следующий пример показывает, как это можно сделать:
stackView.push({item: someItem, properties: {fgcolor: "red", bgcolor: "blue"}}) Примечание: Если элемент объявлен внутри другого элемента, а родительский элемент будет уничтожен (даже если использовался компонент), то дочерний элемент также будет уничтожен. Это соответствует стандартным правилам уничтожения родительско-дочерних элементов Qt, но иногда вызывает удивление у разработчиков.
Жизненный цикл
Жизненный цикл элемента в StackView может иметь следующие переходы:
- создание
- неактивный
- активизация
- активный
- деактивация
- неактивный
- уничтожение
Элемент может любое количество раз перемещаться между состояниями «неактивный» и «активный». Когда элемент активируется, он отображается на экране и считается текущим элементом. Элемент в StackView, который не отображается, не активируется, даже если он в данный момент является верхним элементом в стеке. Когда стек становится видимым, активируется верхний элемент стека. Аналогично, если стек затем скрывается, верхний элемент будет деактивирован. Извлечение элемента из вершины стека в этот момент не приведет к дальнейшей деактивации, поскольку элемент не активен.
Есть связанное свойство Stack.status, которое отслеживает жизненный цикл. Это свойство представляет собой перечисление со следующими значениями: Stack.Inactive, Stack.Activating, Stack.Active и Stack.Deactivating. В сочетании с обычными сигналами Component.onComplete и Component.onDestruction весь жизненный цикл выглядит следующим образом:
- Создан: Component.onCompleted()
- Активизация: Stack.onStatusChanged (Stack.status равен Stack.Activating)
- Активирован: Stack.onStatusChanged (Stack.status равен Stack.Active)
- Деактивация: Stack.onStatusChanged (Stack.status равен Stack.Deactivating)
- Деактивирован: Stack.onStatusChanged (Stack.status равен Stack.Inactive)
- Уничтожение: Component.onDestruction()
Поиск элементов
Иногда необходимо искать элемент, например, для разворачивания стека до элемента, на который у приложения нет ссылки. Для этого используется функция find() в StackView. Функция find() принимает в качестве единственного аргумента функцию обратного вызова. Обратный вызов вызывается для каждого элемента в стеке (начиная с вершины). Если обратный вызов возвращает true, то это означает, что совпадение найдено, и функция find() возвращает этот элемент. Если обратный вызов не возвращает true (совпадение не найдено), то find() возвращает null.
Ниже приведенный код ищет элемент в стеке, у которого есть имя "order_id", а затем разворачивает стек до этого элемента. Обратите внимание, что поскольку find() возвращает null если элемент не найден, а pop разворачивает стек до низа, если в качестве целевого элемента передается null, код работает правильно даже в случае, если соответствующего элемента не найдено.
stackView.pop(stackView.find(function(item) {
return item.name == "order_id";
})); Вы также можете получить доступ к элементу в стеке с помощью get(index). Вы должны использовать эту функцию, если ваш элемент зависит от другого элемента в стеке, так как функция гарантирует, что элемент в заданном индексе загрузится перед его возвратом.
previousItem = stackView.get(myItem.Stack.index - 1));
Переходы
Переход выполняется всякий раз, когда элемент добавляется или удаляется, и состоит из двух элементов: enterItem и exitItem. Сам StackView никогда не перемещает элементы, а вместо этого делегирует эту задачу внешней анимации, заданной стилем или разработчиком приложения. Таким образом, способ, которым элементы визуально должны входить и выходить из стека (и геометрия, с которой они должны закончиться), полностью контролируется извне.
Когда начинается переход, StackView ищет переход, соответствующий выполненной операции. Существует три типа переходов: pushTransition, popTransition и replaceTransition. Каждый из них реализует анимацию входа enterItem и выхода exitItem элементов. Переходы собираются внутри объекта StackViewDelegate, назначенного свойству delegate. По умолчанию popTransition и replaceTransition будут такими же, как pushTransition, если вы не зададите им другое значение.
Простой переход с плавным затуханием можно реализовать так:
StackView {
delegate: StackViewDelegate {
function transitionFinished(properties)
{
properties.exitItem.opacity = 1
}
pushTransition: StackViewTransition {
PropertyAnimation {
target: enterItem
property: "opacity"
from: 0
to: 1
}
PropertyAnimation {
target: exitItem
property: "opacity"
from: 1
to: 0
}
}
}
} PushTransition должен наследоваться от StackViewTransition, который является ParallelAnimation, содержащим свойства enterItem и exitItem. Эти элементы должны быть назначены свойству target анимаций внутри перехода. Поскольку один и тот же экземпляр элемента может быть добавлен в StackView несколько раз, вы всегда должны переопределять StackViewDelegate.transitionFinished(). Реализуйте эту функцию, чтобы сбросить любые анимированные свойства exitItem, чтобы последующие переходы ожидали, что элементы находятся в исходном состоянии.
Более сложный пример может выглядеть следующим образом. Здесь элементы лежат на боку, прежде чем повернуться в вертикальное положение:
StackView {
delegate: StackViewDelegate {
function transitionFinished(properties)
{
properties.exitItem.x = 0
properties.exitItem.rotation = 0
}
pushTransition: StackViewTransition {
SequentialAnimation {
ScriptAction {
script: enterItem.rotation = 90
}
PropertyAnimation {
target: enterItem
property: "x"
from: enterItem.width
to: 0
}
PropertyAnimation {
target: enterItem
property: "rotation"
from: 90
to: 0
}
}
PropertyAnimation {
target: exitItem
property: "x"
from: 0
to: -exitItem.width
}
}
}
} Расширенное использование
Когда StackView нужен новый переход, он сначала вызывает StackViewDelegate.getTransition(). Базовая реализация этой функции просто ищет свойство с именем properties.name внутри себя (корень), как в примерах выше, где она находит property Component pushTransition.
function getTransition(properties)
{
return root[properties.name]
} Вы можете переопределить эту функцию для своего делегата, если вам нужна дополнительная логика для определения того, какой переход возвращать. Например, вы можете проанализировать элементы и возвращать разные анимации в зависимости от их внутреннего состояния. StackView ожидает, что вы вернете компонент, содержащий StackViewTransition, или непосредственно StackViewTransition. Первый вариант проще, так как StackView затем создаст переход и позже уничтожит его, когда он будет завершен, избегая побочных эффектов, вызванных существованием перехода после его завершения. Возвращение StackViewTransition напрямую может быть полезно, если вам нужно реализовать кэширование переходов для повышения производительности. В качестве оптимизации вы также можете вернуть null чтобы указать, что вы хотите просто отобразить/скрыть элементы немедленно без создания или запуска каких-либо переходов. Вы также можете переопределить эту функцию, если вам нужно изменить элементы каким-либо образом перед началом перехода.
properties содержит свойства, которые будут назначены StackViewTransition перед его запуском. На самом деле, вы можете добавить больше свойств к этому объекту во время вызова, если вам нужно инициализировать дополнительные свойства вашего пользовательского StackViewTransition при создании возвращаемого компонента.
Следующий пример показывает, как вы можете выбрать анимацию во время выполнения:
StackViewDelegate {
function getTransition(properties)
{
return (properties.enterItem.Stack.index % 2) ? horizontalTransition : verticalTransition
}
function transitionFinished(properties)
{
properties.exitItem.x = 0
properties.exitItem.y = 0
}
property Component horizontalTransition: StackViewTransition {
PropertyAnimation {
target: enterItem
property: "x"
from: target.width
to: 0
duration: 300
}
PropertyAnimation {
target: exitItem
property: "x"
from: 0
to: target.width
duration: 300
}
}
property Component verticalTransition: StackViewTransition {
PropertyAnimation {
target: enterItem
property: "y"
from: target.height
to: 0
duration: 300
}
PropertyAnimation {
target: exitItem
property: "y"
from: 0
to: target.height
duration: 300
}
}
} Поддерживаемые связанные свойства
Элементы в StackView поддерживают эти связанные свойства:
- Stack.index - Содержит индекс элемента внутри StackView
- Stack.view - Содержит StackView, в котором находится элемент
- Stack.status - Содержит статус элемента
Документация по свойствам
[только для чтения] busy : bool
busy равно true если выполняется переход, и false в противном случае.
[только для чтения] currentItem : Item
Текущий верхний элемент в стеке.
delegate : StackViewDelegate
Переходы, используемые при добавлении или удалении элементов. Для лучшего понимания того, как применять пользовательские переходы, прочитайте Переходы.
См. также Переходы.
[только для чтения] depth : int
Количество элементов, в настоящее время добавленных в стек.
initialItem : var
Первый элемент, который должен быть показан при создании StackView. initialItem может принимать такое же значение, как первый аргумент StackView.push(). Обратите внимание, что это просто удобный способ записи Component.onCompleted: stackView.push(myInitialItem)
Примеры:
- initialItem: Qt.resolvedUrl("MyItem.qml")
- initialItem: myItem
- initialItem: {"item" : Qt.resolvedUrl("MyRectangle.qml"), "properties" : {"color" : "red"}}
См. также push.
Документация по методам
void clear()
Удаляет все элементы из стека. Анимации не будут применяться.
void completeTransition()
Немедленно завершает любой текущий переход. /см. Animation.complete
Item find(function, bool onlySearchLoadedItems = false)
Ищет определенный элемент внутри стека. function будет вызываться для каждого элемента в стеке (с элементом в качестве аргумента) до тех пор, пока функция не вернёт true. Значение возврата будет найденным элементом. Например: find(function(item, index) { return item.isTheOne }) Установите onlySearchLoadedItems в true чтобы не загружать элементы, которые не загружены в память
Item get(int index, bool dontLoad = false)
Возвращает элемент в позиции index в стеке. Если dontLoad равно true, элемент не будет загружен принудительно (и null будет возвращено, если он ещё не загружен)
Элемент pop(Элемент item = undefined)
Извлекает один или несколько элементов из стека.
Функция также может принимать список свойств в качестве аргумента — Item StackView::pop(jsobject dict), который может содержать одно или несколько из следующих свойств:
-
item: если указано, все элементы до (но не включая) item будут извлечены. Если item равноnull, все элементы до (но не включая) первого элемента будут извлечены. Если не указано, будет извлечён только текущий элемент. -
immediate: установите это свойство в значениеtrue, чтобы пропустить эффекты перехода.
Примеры:
- stackView.pop()
- stackView.pop({item:someItem, immediate: true})
- stackView.pop({immediate: true})
- stackView.pop(null)
Примечание: Если необходим только аргумент «item», можно использовать следующий сокращённый синтаксис: stackView.pop(anItem).
Возвращает извлеченный элемент.
См. также clear().
Добавляет item в стек.
Функция также может принимать список свойств в качестве аргумента — Item StackView::push(jsobject dict), который должен содержать одно или несколько из следующих свойств:
- item: это обязательное свойство, содержащее элемент, который требуется добавить.
- properties: список свойств QML, которые должны быть назначены элементу при добавлении. Эти свойства будут скопированы в элемент при его загрузке (в случае компонента или URL) или когда он станет текущим элементом впервые (обычно при добавлении).
-
immediate: установите это свойство в значение
true, чтобы пропустить эффекты перехода. При добавлении массива необходимо установить это свойство только для первого элемента, чтобы сделать всю операцию мгновенной. - replace: установите это свойство в значение, чтобы заменить текущий элемент в стеке. При добавлении массива необходимо установить это свойство только для первого элемента, чтобы заменить столько элементов в стеке, сколько их в массиве.
- destroyOnPop: установите это свойство, чтобы указать, нужно ли уничтожать элемент при его извлечении из стека. По умолчанию (если destroyOnPop не указано), StackView уничтожит элементы, добавленные как компоненты или URL. Элементы, которые не будут уничтожены, будут возвращены к своим родительским элементам, которые были у них до добавления в стек, и скрыты. Если вам необходимо задать это свойство, делайте это с осторожностью, чтобы не допустить утечки памяти.
Также можно добавить массив элементов (списки свойств), если нужно добавить несколько элементов за один раз. Переход тогда будет осуществляться только между текущим элементом и последним элементом в списке. Загрузка остальных элементов будет отложена до необходимости.
Примеры:
- stackView.push({item:anItem})
- stackView.push({item:aURL, immediate: true, replace: true})
- stackView.push({item:aRectangle, properties:{color:"red"}})
- stackView.push({item:aComponent, properties:{color:"red"}})
- stackView.push({item:aComponent.createObject(), destroyOnPop:true})
- stackView.push([{item:anitem, immediate:true}, {item:aURL}])
Примечание: Если необходим только аргумент «item», можно использовать следующий сокращённый синтаксис: stackView.push(anItem).
Возвращает элемент, который стал текущим.
См. также initialItem и Добавление элементов.
© The Qt Company Ltd
Licensed under the GNU Free Documentation License, Version 1.3.
https://doc.qt.io/qt-5.15/qml-qtquick-controls-stackview.html