Тип 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 реализует модель навигации на основе стека, которая может использоваться с набором взаимосвязанных страниц информации. Элементы помещаются в стек по мере углубления пользователя в материал, и извлекаются обратно, когда он выбирает возврат назад.
Пример галереи касаний touch gallery — хороший отправной пункт для понимания работы StackView. Следующий фрагмент из примера показывает, как его можно использовать:
StackView {
id: stack
initialItem: view
Component {
id: view
MouseArea {
Text {
text: stack.depth
anchors.centerIn: parent
}
onClicked: stack.push(view)
}
}
} Использование StackView в приложении
Использование StackView в приложении обычно сводится к добавлению StackView как дочернего элемента окна. Стек обычно привязан к границам окна, за исключением верхней или нижней части, где он может быть привязан к строке состояния или к какому-либо другому подобному UI-компоненту. Затем стек можно использовать, вызывая его методы навигации. Первый элемент, который нужно отобразить в StackView, — это элемент, назначенный свойству initialItem.
Примечание: Элементы, помещенные в стек, имеют прикреплённые свойства Stack.
Базовая навигация
Существует три основных операции навигации в 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}]) END_OF_DOCUMENT_MARKER Если элемент встраивается, то элемент временно становится дочерним элементом 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()
Немедленно завершить любой текущий переход. /sa Animation.complete
Элемент find(функция, bool толькоИскатьЗагруженныеЭлементы = false)
Поиск определенного элемента внутри стека. функция будет вызываться для каждого элемента в стеке (с элементом в качестве аргумента), пока функция не вернёт значение true. Возвращаемое значение — найденный элемент. Например: find(function(item, index) { return item.isTheOne }) Установите толькоИскатьЗагруженныеЭлементы в true для того, чтобы не загружать элементы, которые не загружены в память.
Элемент get(int индекс, bool неЗагружать = false)
Возвращает элемент в позиции индекс в стеке. Если неЗагружать равно true, элемент не будет вынужден загружаться (и null будет возвращено, если он ещё не загружен).
Элемент pop(Элемент элемент = undefined)
Извлекает один или несколько элементов из стека.
Функция также может принимать список свойств в качестве аргумента — Item StackView::pop(jsobject dict), который может содержать одно или несколько из следующих свойств:
-
item: если указано, все элементы до (но не включая) элемент будут извлечены. Если элемент равенnull, все элементы до (но не включая) первого элемента будут извлечены. Если не указано, будет извлечён только текущий элемент. -
immediate: установите это свойство вtrueдля пропуска эффектов перехода.
Примеры:
- stackView.pop()
- stackView.pop({item:someItem, immediate: true})
- stackView.pop({immediate: true})
- stackView.pop(null)
Примечание: Если единственным необходимым аргументом является «элемент», вы можете применить следующее сокращение: stackView.pop(anItem).
Возвращает элемент, который был извлечён.
См. также clear().
Добавляет элемент в стек.
Функция также может принимать список свойств в качестве аргумента — 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}])
Примечание: Если единственным необходимым аргументом является «элемент», вы можете применить следующее сокращение: stackView.push(anItem).
Возвращает элемент, который стал текущим.
См. также initialItem и Добавление элементов.
© The Qt Company Ltd
Licensed under the GNU Free Documentation License, Version 1.3.
https://doc.qt.io/qt-5.12/qml-qtquick-controls-stackview.html