Тип QML StackView
Обеспечивает модель навигации на основе стека. Подробнее...
| Заявление об импорте: | import QtQuick.Controls 1.4 |
| С момента: | Qt 5.1 |
| Наследует: |
Свойства
- busy : bool
- currentItem : Элемент
- delegate : StackViewDelegate
- depth : int
- initialItem : var
Методы
- void clear()
- void completeTransition()
- Элемент find(функция, bool толькоПоискЗагруженныхЭлементов)
- Элемент get(int индекс, bool неЗагружать)
- Элемент pop(Элемент элемент)
- Элемент push(Элемент элемент)
Подробное описание
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.
Примечание: Элементы, помещенные в стек просмотра, имеют присоединенные свойства стека.
Основная навигация
Существует три основных операции навигации в 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, может быть элементом, 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 в списке аргументов, переданных для вставки.
Если 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
Элемент 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/archives/qt-5.6/qml-qtquick-controls-stackview.html