qml 导航类视图
1、ScrollView
在另一个Item中提供滚动视图,ScrollView可以用来替换Flickable,也可以装饰现有的Flickable。根据平台的不同,它将添加滚动条和内容框架。Flickable没有滚动条,通过上线滑动实现滚动,用于触摸设备界面比较适合。
只有一个Item可以是ScrollView的直接子视图,并且子视图被隐式锚定以填充滚动视图。
例如:
ScrollView { Image { source: "largeImage.png" } }
在例子中,Image项将隐式地获得滚动行为,就像它在Flickable中使用一样。子项目的宽度和高度将用于定义内容区域的大小。
可以通过指定ScrollViewStyle为ScrollView创建一个自定义外观。
- [default] contentItem : Item ScrollView的内容。这由用户设置。请注意,contententitem的定义与Flickable的定义有些不同,在Flickable中contententitem是隐式创建的。
- [read-only] flickableItem : Item ScrollView的flickableItem。如果提供给ScrollView的contententitem是一个Flickable,它将是contententitem。
- frameVisible : bool 这个属性告诉ScrollView是否应该在它的内容周围呈现一个框架。缺省值为false。
- highlightOnFocus : bool 当ScrollView有输入焦点时,这个属性控制框架周围是否应该有高亮显示。缺省值为false。
- horizontalScrollBarPolicy : enumeration 此属性保存显示水平滚动条的策略。可以是以下任意值(默认策略是Qt.ScrollBarAsNeeded):
- Qt.ScrollBarAsNeeded
- Qt.ScrollBarAlwaysOff
- Qt.ScrollBarAlwaysOn
- style : Component 此控件的样式组件。
- verticalScrollBarPolicy : enumeration 此属性保存显示垂直滚动条的策略。可以是以下任意值(默认策略是Qt.ScrollBarAsNeeded):
- Qt.ScrollBarAsNeeded
- Qt.ScrollBarAlwaysOff
- Qt.ScrollBarAlwaysOn
- viewport : Item 视口决定了contententitem上的当前“窗口”。换句话说,它剪辑它,视口的大小告诉你有多少内容区域是可见的。
1.1 ScrollViewStyle
- control : ScrollView 这个样式所附加的ScrollView
- corner : Component 此组件绘制滚动条之间的角区
- decrementControl : Component 该组件控制滚动条递减按钮的外观。可以访问以下状态属性:
-
property bool styleData.hovered
- property bool styleData.pressed
- property bool styleData.horizontal
-
- frame : Component 这个组件在滚动条周围绘制框架。
- handle : Component 该组件控制滚动条手柄的外观。可以访问以下状态属性:
-
-
property bool styleData.hovered
- property bool styleData.pressed
- property bool styleData.horizontal
-
- handleOverlap : int 此属性控制手柄与递增/递减按钮之间的边缘重叠。缺省值是30。
- incrementControl : Component 该组件控制滚动条增量按钮的外观。可以访问以下状态属性:
-
property bool styleData.hovered
- property bool styleData.pressed
- property bool styleData.horizontal
-
- minimumHandleLength : int 这是滚动条句柄的最小范围。
- scrollBarBackground : Component 这个组件控制滚动条背景的外观。可以访问以下状态属性:
-
property bool styleData.hovered
- property bool styleData.pressed
-
- scrollToClickedPosition : bool 该组件决定当单击时,该flickable是否应该在鼠标位置重新定位自己。
- transientScrollBars : bool 此属性保存滚动条是否为瞬态。当内容滚动时,临时滚动条会出现,当不再需要时,滚动条会消失。默认值是平台相关的。
2、SplitView
SplitView是一个可以水平或垂直放置项目的控件,每个项目之间都有一个可拖动的分隔符。
在SplitView中总是会有一个(且只有一个)具有 Layout.fillWidth 设置为true(或 Layout.fillHeight,如果方向是Qt.Vertical)。这意味着当其他项目被放置时,项目将得到所有剩余的空间。默认情况下,SplitView的最后一个可见的子元素会有这个设置,但是它可以通过在另一个项上显式地将fillWidth设置为true来改变。
由于fillWidth项目将自动调整大小以适应额外的空间,显式的分配其宽度和高度属性将被忽略(但 Layout.minimumWidth 和 Layout.maximumWidth 仍然会生效)。其他项目的初始大小应该通过它们的宽度和高度属性来设置。当用户拖动项的拆分器句柄时,任何对项的宽度或高度的绑定赋值都会被打破。
句柄可以属于左侧或顶部的项,也可以属于右侧或底部的项:
如果fillWidth项在右边:句柄属于左边的项。
如果fillWidth项目在左边:句柄属于右边的项目。
这将再次控制当用户拖动一个句柄时,哪个项目会被调整大小,以及当一个项目被告知隐藏时,哪个句柄会被隐藏。
SplitView支持在子项目上设置附加布局属性,这意味着你可以为每个子项目设置以下附加属性:
- Layout.minimumWidth
- Layout.minimumHeight
- Layout.maximumWidth
- Layout.maximumHeight
- Layout.fillWidth (
true
for only one child) - Layout.fillHeight (
true
for only one child)
例子: 要创建一个有三个项的SplitView,并让中心项获得多余的空间,可以这样做:
SplitView { anchors.fill: parent orientation: Qt.Horizontal Rectangle { width: 200 Layout.maximumWidth: 400 color: "lightblue" Text { text: "View 1" anchors.centerIn: parent } } Rectangle { id: centerItem Layout.minimumWidth: 50 Layout.fillWidth: true color: "lightgray" Text { text: "View 2" anchors.centerIn: parent } } Rectangle { width: 200 color: "lightgreen" Text { text: "View 3" anchors.centerIn: parent } } }
- handleDelegate : Component 此属性保存将在每个子项目之间实例化的委托。在委托内部,以下属性是可用的:
readonly property bool styleData.index | Specifies the index of the splitter handle. The handle between the first and the second item will get index 0, the next handle index 1 etc. |
readonly property bool styleData.hovered | The handle is being hovered. |
readonly property bool styleData.pressed | The handle is being pressed. |
readonly property bool styleData.resizing | The handle is being dragged. |
- orientation : int 这个属性保存了SplitView的方向。取值为Qt.Horizontal或Qt.Vertical。默认值为Qt.Horizontal。
- resizing : bool 当用户通过拖动拆分器句柄来调整任何项的大小时,此属性为真。
- void addItem(Item item)
- void removeItem(Item item)
3、StatckView
Properties
-
- busy : bool 如果转换正在运行,Busy为真,否则为假。
- currentItem : Item 堆栈中当前最顶部的项。
- delegate : StackViewDelegate 推或弹出项时要使用的转换
- depth : int 当前推入堆栈的项数。
- initialItem : var StackView创建时应该显示的第一个项目。initialItem可以接受与StackView.push()的第一个参数相同的值
Methods
-
- void clear() 从堆栈中移除所有项。没有动画将被应用。
- void completeTransition() 立即完成任何正在进行的过渡
- Item find(function, bool onlySearchLoadedItems) 在堆栈中搜索特定项。函数将被调用堆栈中的每一项(以该项作为参数),直到函数返回true。返回值将是找到的项目。例如:find(function(item, index) {return item。isTheOne})将onlySearchLoadedItems设置为true,表示不加载未加载到内存中的项目
- Item get(int index, bool dontLoad) 返回堆栈中位于索引位置的项。如果dontLoad为true,该项目将不会被强制加载(如果还没有加载,则返回null)
- Item pop(Item item) 从堆栈中弹出一个或多个项目。 这个函数也可以接受一个属性列表作为参数- Item StackView::pop(jsobject dict),它可以包含一个或多个以下属性:
item
: 如果指定了,所有到(但不包括)Item的项都将弹出。如果item为空,将弹出到(但不包括)第一个项目的所有项目。如果未指定,则只有当前项将弹出。返回弹出的项目immediate
: 将此属性设置为true,跳过转换效果。
- Item push(Item item) 将项压入堆栈。这个函数也可以接受一个属性列表作为参数- Item StackView::push(jsobject dict),它应该包含一个或多个以下属性:
- item: 这个属性是必需的,它保存了你想要推送的项目。
- properties: 在push时应该分配给项目的QML属性列表。这些属性将在项目被加载时(对于组件或URL),或者当它第一次成为当前项目时(通常是在推送时)被复制到项目中。
- immediate: 将此属性设置为true,跳过转换效果。当push一个数组时,您只需要在第一个元素上设置这个属性,就可以立即执行整个操作。
- replace: 设置此属性以替换堆栈上的当前项。当push一个数组时,你只需要在第一个元素上设置这个属性,就可以替换堆栈中和数组中一样多的元素。
- destroyOnPop:设置这个属性来指定当物品弹出堆栈时是否需要销毁它。默认情况下(如果没有指定destroyOnPop), StackView将销毁作为组件或url推送的项目。未被销毁的物品在被推到堆栈之前,将被重新父代到原来的父代,并被隐藏。如果需要设置此属性,请谨慎操作,以免条目泄漏。如果需要一次推送多个项目,还可以推送一个项目数组(属性列表)。转换将只发生在列表中的当前项和最后一项之间。其他项目的加载将推迟到需要时。
Using StackView in an Application
在应用程序中使用StackView通常是一个简单的事情,添加StackView作为一个窗口的子窗口。堆栈通常固定在窗口的边缘,除了在顶部或底部,它可能固定在状态栏或其他类似的UI组件。然后可以通过调用堆栈的导航方法来使用堆栈。StackView中显示的第一项是分配给initialItem的项。
1、Basic Navigation 基本的导航
在StackView中有三个主要的导航操作:push(), pop()和replace(通过在push()中指定参数replace来替换)。这些对应于经典的堆栈操作,“push”将一个条目添加到堆栈之上,“pop”从堆栈中删除项顶部,而“replace”就像一个pop,后跟一个推动,它取代了最高的项目在堆栈上新项目(但应用国铁可能有所不同)。堆栈中最顶部的项对应于当前在屏幕上可见的项。这意味着“push”在逻辑上等同于导航到应用程序的深处,“pop”相当于导航回来,而“replace”则等同于替换当前项。
有时需要返回到堆栈中的不止一个步骤,例如,返回到应用程序中的“主”项或某种节项。对于这个用例,可以将一个项指定为pop()的参数。当堆栈被unwind到指定的项时,这被称为“unwind”操作。如果未找到该项,则堆栈展开,直到堆栈中只有一个项时,该项才成为当前项。为了显式地展开到堆栈的底部,建议使用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] -“replace” C切换到D
- pop(A) => [A] -“pop” C切换到A
注意:当堆栈为空时,push()将不会执行过渡动画,因为没有东西可以进行过渡(通常在应用程序启动期间)。在深度为1或0的堆栈上执行pop()是不操作的。如果需要从堆栈中移除所有项,则可以使用单独的函数clear()。
调用push()将返回被推入堆栈的项。调用pop()将返回从堆栈中弹出的项。当在unwind操作中调用pop()时,将返回最顶部的项(弹出的第一个项,也将是转换出去的项)。
2、Deep Linking 深度链接
深度链接意味着将应用程序启动到特定的状态。例如,可以启动一个报纸应用程序来显示一篇特定的文章,绕过通常需要导航到相关文章的前端项目(可能还有部分项目)。就StackView而言,深度链接意味着可以修改堆栈的状态,以至于可以将一组项目推到堆栈的顶部,或者完全将堆栈重置到给定的状态。
StackView中用于深度链接的API与用于基本导航的API相同。推入一个数组而不是一个单独的项目,将涉及到该数组中的所有项目将被推入堆栈。然而,转换动画将被执行,就好像只有数组中的最后一项被推入堆栈一样。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] -“replace” C切换到F
- clear(); push([D, E, F]) => [D, E, F] - 没有切换动作(因为堆栈为空)
3、Pushing items
推送到StackView的项目可以是一个项目,一个URL,一个包含URL的字符串,或者一个组件。要推送它,将它分配给属性列表中的一个属性“item”,并将它作为参数传递给推送:
stackView.push({item: yourItem})
该列表可以包含几个属性来控制项目应该如何被推送:
-
- Item:这个属性是必需的,保存要推送的项目。
- properties:在push时分配给项目的QML属性列表。这些属性将在加载时复制到项目中,或者当项目将成为当前项目时(通常是在推送时)。
-
mmediate:将此属性设置为true,跳过转换效果。当push一个数组时,只需要在第一个元素上设置这个属性,就可以立即执行整个操作。
- Replace:设置此属性以替换堆栈上的当前项。当push一个数组时,你只需要在第一个元素上设置这个属性,就可以替换堆栈中和数组中一样多的元素。
- destroyOnPop:设置这个布尔值为true,如果StackView需要销毁从栈中弹出的项目。默认情况下(如果没有指定destroyOnPop), StackView将销毁作为组件或url推送的项目。未被销毁的物品在被推到堆栈和隐藏之前,将被重新父母回到原来的父母。如果需要设置此属性,请谨慎操作,以免条目泄漏。
如果唯一需要的参数是"item",可以应用以下简写符号:
stackView.push(yourItem)
通过使用属性列表数组,您可以一次推入多个项目。这比一个一个地推送项目更有效,因为StackView可以只加载列表中的最后一个项目。其余的将被加载,因为它们即将成为当前项目(这发生在堆栈弹出时)。下面的例子展示了如何推送一个项目数组:
stackView.push([{item: yourItem1}, {item: yourItem2}])
如果一个内联项目被推入,该项目会暂时被重新父化到StackView中。当项目被弹出时,它会重新回到原来的主人那里。但是,如果一个项目作为一个组件或URL被推送,那么实际的项目将作为该组件的一个项目创建。当该项即将成为堆栈中的当前项时,这将自动发生。该项目的所有权通常会被StackView拿走,当该项目被弹出时,StackView会自动销毁该项目品。相比之下,声明该项目的组件保留在应用程序的所有权中,不会被堆栈销毁。这可以通过在push参数列表中显式设置destroyOnPop来覆盖。
如果指定了要推送的属性,它们将在加载时(对于组件或URL)或当项目变成当前项目时(对于内联项目)被复制到项目中。下面的例子展示了如何做到这一点:
stackView.push({item: someItem, properties: {fgcolor: "red", bgcolor: "blue"}})
注意:如果一个项目在另一个项目中声明,并且父项目被销毁,(即使使用了组件),子项目也将被销毁。这遵循正常的Qt父子销毁规则,但有时会让开发人员感到意外。
4、Lifecycle 生命周期
StackView中一个项目的生命周期可以有以下转换:
-
- instantiation
- inactive
- activating
- active
- deactivating
- inactive
- destruction
它可以在非活动和活动之间移动任意次数。当一个项目被激活时,它在屏幕上是可见的,并被认为是当前项目。StackView中不可见的项不会被激活,即使该项当前是堆栈中最顶部的项。当堆栈变得可见时,最上面的项目被激活。同样,如果堆栈被隐藏,最上面的项将被禁用。此时将项从堆栈顶部取出不会导致进一步的失活,因为该项不是活动的。
有一个附加的堆栈。跟踪生命周期的状态属性。此属性是具有以下值的枚举:Stack.Activating, Stack.Active and Stack.Deactivating 与组件的信号Component.onComplete 和Component.onDestruction相结合,整个生命周期是:
-
- Created: Component.onCompleted()
- Activating: Stack.onStatusChanged (Stack.status is Stack.Activating)
- Acivated: Stack.onStatusChanged (Stack.status is Stack.Active)
- Deactivating: Stack.onStatusChanged (Stack.status is Stack.Deactivating)
- Deactivated: Stack.onStatusChanged (Stack.status is Stack.Inactive)
- Destruction: Component.onDestruction()
5、Finding items 查找项目
例如,为了将堆栈展开到应用程序没有引用的项,有时需要搜索项。在StackView中使用find()函数来实现这一点。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));
6、Transitions
每当一个项目被推送或弹出时,一个转换就会被执行,它由两个项目组成:enterItem和exitiitem。StackView本身永远不会移动项目,而是将这项工作委托给样式或应用程序开发者提供的外部动画集。因此,项目如何从视觉上进入和离开堆栈(以及它们最终的几何形状)完全由外部控制。
当转换开始时,StackView将搜索与执行的操作匹配的转换。有三个转换可供选择:pushTransition、popTransition和replaceTransition。每个都实现了enterItem如何动画化的导入和退出。转换被收集在一个分配给delegate的StackViewDelegate对象中。默认情况下,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和exitiitem属性。这些项目应该被分配给转换动画的目标属性。因为相同的条目实例可以被多次推送到StackView中,所以你应该总是覆盖StackViewDelegate.transitionFinished()。实现此函数来重置exitiitem上的任何动画属性,以便以后的转换可以预期项目处于默认状态。
一个更复杂的示例可能如下所示。在这里,项目在被旋转到一个直立的位置之前是放在一边的:
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 } } } }
5.1 Advanced usage 高级用法
当StackView需要一个新的转换时,它首先调用StackViewDelegate.getTransition()。这个函数的基本实现只是在它自身(根)中查找一个名为properties.name的属性,这就是它在上面的例子中查找属性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 } } }
5.2 Supported Attached Properties
Items in a StackView support these attached properties:
-
- Stack.index - Contains the index of the item inside the StackView
- Stack.view - Contains the StackView the item is in
- Stack.status - Contains the status of the item
4、TabView
TabView为您的应用程序提供了基于选项卡的导航模型。例如,下面的代码片段使用标签来在每个标签页上显示不同颜色的矩形:
TabView { Tab { title: "Red" Rectangle { color: "red" } } Tab { title: "Blue" Rectangle { color: "blue" } } Tab { title: "Green" Rectangle { color: "green" } } }
-
[read-only] contentItem : Item
这个属性保存选项卡视图的内容项。被声明为TabView子元素的标签会自动成为TabView的contententitem的父元素。 - [read-only] count : int 当前的标签数
- currentIndex : int 当前标签索引
- frameVisible : bool 标签框围绕内容的可见性
- tabPosition : int
- Qt.TopEdge (default)
- Qt.BottomEdge
- tabsVisible : bool 标签栏的可见性
Method Documentation
- Tab addTab(string title, Component component) 添加一个带有给定标题和可选组件的新选项卡。返回新添加的选项卡。
-
Tab getTab(int index) Returns the Tab item at index.
- Tab insertTab(int index, string title, Component component) 在索引处插入一个新选项卡,带有给定的标题和一个可选组件。返回新添加的选项卡。
- void moveTab(int from, int to) Moves a tab from index to another
- void removeTab(int index) Removes and destroys a tab at the given index
4.1 TabViewStyle
提供TabView的自定义样式…
TabView {
id: frame
anchors.fill: parent
anchors.margins: 4
Tab { title: "Tab 1" }
Tab { title: "Tab 2" }
Tab { title: "Tab 3" }
style: TabViewStyle {
frameOverlap: 1
tab: Rectangle {
color: styleData.selected ? "steelblue" :"lightsteelblue"
border.color: "steelblue"
implicitWidth: Math.max(text.width + 4, 80)
implicitHeight: 20
radius: 2
Text {
id: text
anchors.centerIn: parent
text: styleData.title
color: styleData.selected ? "white" : "black"
}
}
frame: Rectangle { color: "steelblue" }
}
}
- [read-only] control : TabView 这个样式所附加的ScrollView。
-
frame : Component 这定义了制表符框架。
-
frameOverlap : int 这个属性保存了单个标签按钮和框架之间的重叠数量。
-
leftCorner : Component 左边角
-
rightCorner : Component 右边角
-
tab : Component 这定义了选项卡。你可以通过styleData属性访问标签状态,使用以下属性:
readonly property int styleData.index | This is the current tab index. |
readonly property bool styleData.selected | This is the active tab. |
readonly property string styleData.title | Tab title text. |
readonly property bool styleData.nextSelected | The next tab is selected. |
readonly property bool styleData.previousSelected | The previous tab is selected. |
readonly property bool styleData.pressed | The tab is being pressed. (since QtQuick.Controls.Styles 1.3) |
readonly property bool styleData.hovered | The tab is being hovered. |
readonly property bool styleData.enabled | The tab is enabled. (since QtQuick.Controls.Styles 1.2) |
readonly property bool styleData.activeFocus | The tab button has keyboard focus. |
readonly property bool styleData.availableWidth | The available width for the tabs. |
readonly property bool styleData.totalWidth | The total width of the tabs. (since QtQuick.Controls.Styles 1.2) |
- tabBar : Component 这定义了标签栏的背景。
-
tabOverlap : int 此属性保存单个选项卡按钮之间重叠的数量。
-
tabsAlignment : int 此属性保存选项卡按钮的水平对齐方式。支持的值是:
- Qt.AlignLeft (default)
- Qt.AlignHCenter
- Qt.AlignRight
- tabsMovable : bool 这个属性保存用户是否可以移动选项卡。默认情况下,不能移动。
5、SwipeView
SwipeView提供了一个基于滑动的导航模型。
SwipeView使用一组页面填充。一个页面是可以看到的。用户可以通过向下滑动来在页面之间进行导航。注意,SwipeView本身完全是非可视化的。建议将其与页面显示相结合,给用户一个有多个页面的视觉提示。
SwipeView {
id: view
currentIndex: 1
anchors.fill: parent
Item {
id: firstPage
}
Item {
id: secondPage
}
Item {
id: thirdPage
}
}
PageIndicator {
id: indicator
count: view.count
currentIndex: view.currentIndex
anchors.bottom: view.bottom
anchors.horizontalCenter: parent.horizontalCenter
}
如上所示,SwipeView通常使用一组静态页面来填充,这些静态页面被定义为视图的子视图。还可以在运行时动态地添加、插入、移动和删除页面。
通常不建议在SwipeView中添加过多的页面。但是,当页面的数量变大,或者单个页面相对复杂时,可能希望通过卸载无法访问的页面来释放资源。下面的例子展示了如何使用Loader来保持最多三个页面同时被实例化。
SwipeView {
Repeater {
model: 6
Loader {
active: SwipeView.isCurrentItem || SwipeView.isNextItem || SwipeView.isPreviousItem
sourceComponent: Text {
text: index
Component.onCompleted: console.log("created:", index)
Component.onDestruction: console.log("destroyed:", index)
}
}
}
}
注意:SwipeView接管了添加到视图中的项目的几何管理。不支持在项目上使用锚,任何宽度或高度的分配都将被视图覆盖。注意,这只适用于项目的根目录。指定宽度和高度,或为其子节点使用锚定,都可以正常工作。
- interactive : bool 这个属性描述用户是否可以与SwipeView交互。用户不能滑动非交互式的视图。默认值为true。
-
orientation : enumeration 这个属性保存方向 Qt.Horizontal(default) 和 Qt.Vertical
- [read-only] SwipeView.index : int 这个附加属性保存SwipeView中每个子项目的索引。它被附加到SwipeView的每个子条目上。
-
[read-only] SwipeView.isCurrentItem : bool 如果此子项是当前项,则此附加属性为真。
-
[read-only] SwipeView.isNextItem : bool 如果此子项是下一项,则此附加属性为真。
-
[read-only] SwipeView.isPreviousItem : bool 如果此子项是前一项,则此附加属性为真。
-
[read-only] SwipeView.view : SwipeView 此附加属性保存管理此子项目的视图。
5.1 PageIndicator
PageIndicator用于指示一个包含多个页面的容器中当前活动的页面。PageIndicator由呈现页面的委托项组成。
Column {
StackLayout {
id: stackLayout
Page {
// ...
}
Page {
// ...
}
Page {
// ...
}
}
PageIndicator {
currentIndex: stackLayout.currentIndex
count: stackLayout.count
}
}
-
count : int 此属性保存页面的数量。
-
currentIndex : int 此属性保存当前页的索引。
-
delegate : Component 此属性保存显示页面的委托。以下属性在每个委托的上下文中是可用的:
- index : int The index of the item
- pressed : bool Whether the item is pressed
- interactive : bool 此属性保存控件是否是交互式的。交互式页面指示器对按下做出反应,并自动适当地更改当前索引。缺省值为false。
SwipeView {
id: view
currentIndex: pageIndicator.currentIndex
anchors.fill: parent
Page {
title: qsTr("Home")
}
Page {
title: qsTr("Discover")
}
Page {
title: qsTr("Activity")
}
}
PageIndicator {
id: pageIndicator
interactive: true
count: view.count
currentIndex: view.currentIndex
anchors.bottom: parent.bottom
anchors.horizontalCenter: parent.horizontalCenter
}
注意:页面指示器通常是非常小的(为了避免用户从用户界面的实际内容上分心)。它们可能很难点击,而且可能不容易被用户识别为交互式的。由于这些原因,它们最好用于补充主要的导航方法(如SwipeView),而不是取代它们。
Customizing PageIndicator
PageIndicator由背景、内容项和委托组成。
import QtQuick 2.6
import QtQuick.Controls 2.1
PageIndicator {
id: control
count: 5
currentIndex: 2
delegate: Rectangle {
implicitWidth: 8
implicitHeight: 8
radius: width / 2
color: "#21be2b"
opacity: index === control.currentIndex ? 0.95 : pressed ? 0.7 : 0.45
Behavior on opacity {
OpacityAnimator {
duration: 100
}
}
}
}
Customizing SwipeView
SwipeView可以有一个可视的背景项。导航是由内容项实现的。
import QtQuick 2.6
import QtQuick.Controls 2.1
SwipeView {
id: control
background: Rectangle {
color: "#eeeeee"
}
}
Customizing SwipeDelegate
SwipeDelegate由6个可视项目组成: background, content item, indicator, swipe. left, swipe. right, and swipe.behind.
import QtQuick 2.6
import QtQuick.Controls 2.1
SwipeDelegate {
id: control
text: qsTr("SwipeDelegate")
Component {
id: component
Rectangle {
color: SwipeDelegate.pressed ? "#333" : "#444"
width: parent.width
height: parent.height
clip: true
Label {
text: qsTr("Press me!")
color: "#21be2b"
anchors.centerIn: parent
}
}
}
swipe.left: component
swipe.right: component
contentItem: Text {
text: control.text
font: control.font
color: control.enabled ? (control.down ? "#17a81a" : "#21be2b") : "#bdbebf"
elide: Text.ElideRight
verticalAlignment: Text.AlignVCenter
Behavior on x {
enabled: !control.down
NumberAnimation {
easing.type: Easing.InOutCubic
duration: 400
}
}
}