Fluid UI
具有动画效果的流UI界面——Fluid UIs
- 界面上的组件能以动画的形态做出连续变化,而不是突然显示、隐藏。
- Qt Quick 提供了多种创建动画流UI界面的方法,主要有:
- 使用状态切换机制
- 设计组合动画
状态和切换
-
状态:
- Qt Quick允许用户在
State
对象中声明各种不同的UI状态。 - 状态对象中有个属性改变(
PropertyChanges
)的元素,不同的UI状态可通过该元素设置状态切换时基本属性的目标值,使用户组织UI界面逻辑。
- Qt Quick允许用户在
-
切换:
- 切换是一种与元素相关联的对象,它定义了当该元素的状态发生改变时,其属性将以怎样的动画方式呈现。
-
states
属性是Item
元素的属性,同样也有获得当前状态的属性state
:- states : list
- state : string(如果没有在状态列表中设置该元素的状态,则默认返回空串)
-
举个例子:
-
Text { id: text_ID color: "grey" //初始文字显示为灰色 font.family: "Source Code Pro" //字体 font.pointSize: 14 //初始字号为12 font.bold: true //加粗 //该元素的所有状态列表 states: [ State { name: "highlight" when: mouseArea_ID.pressed PropertyChanges { target: stext color: "red" font.pointSize: 25 //以艺术字呈现 style: Text.Raised styleColor: "red" } } ] transitions: [ Transition { PropertyAnimation { duration: 1000 } } ] MouseArea { //能接受鼠标单击 id: mouseArea_ID anchors.fill: parent } }
-
states
属性包含所有的状态列表,如果只有一个状态,可以省略[ ]
; -
State
元素:- 可以指定被改变的属性:
[default] changes : list<Change>
; - 也可以在里面创建
PropertyChanges
元素; - 也可以修改其他对象的属性(不仅仅是拥有该状态的对象);
- 除此之外,
State
还能:- 使用
StateChangeScript
运行一些脚本; - 使用
PropertyChanges
为一个对象重写现有的信号处理; - 使用
PropertyChanges
为一个元素重定义一个父元素; - 使用
AnchorChanges
修改锚点的值;
- 使用
- 可以指定被改变的属性:
-
name
属性:-
其中
name
属性可以指定状态的名称,每一个状态对象都有一个在本元素中唯一的名称,默认为空串; -
一个元素可以将其
state
属性设为空串来明确的将其状态设置为默认状态(初始化元素的属性值); -
要改变一个元素的当前状态,可以将其
state
属性设置为要改变的状态名,例如: -
Rectangle { id: myRect width: 100; height: 100 color: "black" MouseArea { id: mouseArea anchors.fill: parent onClicked: myRect.state == 'clicked' ? myRect.state = "" : myRect.state = 'clicked'; } states: [ State { name: "clicked" PropertyChanges { target: myRect; color: "red" } } ] }
-
-
when
属性:- 该属性设置了什么时候进入这个状态,类型是
bool
型; - 所有的QML可视元素都有一个默认状态,在默认状态下包含了该元素所有的初始化属性值;
- 元素可以不设置
when
属性,但是要明确什么时候变为该状态;
- 该属性设置了什么时候进入这个状态,类型是
-
Transition
元素:- 元素在不同状态间改变时使用
transition
属性来实现动画效果; - 注意,单个
Transition
不需要设置动画中的from
和to
属性,因为在状态改变的开始之前和结束之后会自动设置;from
属性会被设置为当前值,to
属性会设为PropertyChanges
中的值。
- 元素在不同状态间改变时使用
组合动画
单一的动画可以组合成一个复合动画,想要运行复杂的动画,可以在一个动画组中进行设计。
ParallelAnimation
:在这个动画组中的动画会并行(同时)运行;SequentialAnimation
:在这个动画组的动画会依次运行(串行);- 注意,一旦独立的动画被放入这两个动画组中,就不能在单独开始或停止,串行和并行动画都必须作为一个组进行开始和停止;
举个简单的例子:
-
Rectangle { //水平往返移动的矩形背景区 id: rectangle_ID width: 500 height: 600 color: "grey" clip: true //使得矩形内部的元素不超过矩形边框 Image { //图像元素显示照片 id: image_ID source: "qrc:/Pictures/Used_Images/Pictures/01_QML.png" //照片沿垂直中线下落 anchors.horizontalCenter: parent.horizontalCenter y: 0 //初始时位于顶端 scale: 0.1 //大小为原尺寸的1/10 opacity: 0 //初始透明度为0(不可见) rotation: 45 //初始放置的角度 } MouseArea { anchors.fill: parent onClicked: { rectangleSequentialAnimation_ID.running = true //开启水平方向(矩形往返)动画 imageSequentialAnimation_ID.running = true //开启垂直方向(照片掉落)动画 } } //矩形的动画组 SequentialAnimation on x { id: rectangleSequentialAnimation_ID running: false //初始时关闭动画 loops: Animation.Infinite //设置动画组一直运行 //实现往返运动 NumberAnimation { from: 0 to: parent.parent.width - rectangle_ID.width duration: 8000 easing.type: Easing.InOutQuad } NumberAnimation { // from: parent.parent.width - rectangle_ID.width to: 0 duration: 8000 easing.type: Easing.InOutQuad } //在动画中间进行暂停 PauseAnimation { duration: 1000 } } //图像的动画组 SequentialAnimation { id: imageSequentialAnimation_ID loops: Animation.Infinite //设置动画组一直运行 ParallelAnimation { ScaleAnimator { //缩放动画 target: image_ID to: 1 duration: 2000 } OpacityAnimator { //透明度动画 target: image_ID to: 1 duration: 3000 } RotationAnimator { //旋转动画 target: image_ID to: 360 duration: 2000 } NumberAnimation { target: image_ID property: "y" to: rectangle_ID.height - image_ID.height //运动到矩形区的底部 easing.type: Easing.OutBounce //为造成照片落地后又“弹起”的效果 duration: 5000 } } PauseAnimation { duration: 2000 } ParallelAnimation { //重回初始状态 NumberAnimation { target: image_ID property: "y" to: 0 easing.type: Easing.OutQuad duration: 1000 } OpacityAnimator { target: image_ID to: 0 duration: 1000 } } } }
展示图:
解释:
- 矩形的动画组
SequentialAnimation on x
,这个串行的动画作为属性值源应用在了矩形的x
属性上,不需要指定目标和属性,组内的动画也都会应用到矩形的x
属性上; - 图像的动画组
SequentialAnimation
没有定义到任何属性上,所以组中的各个子动画都需要明确目标(target
)和属性(property
); - 动画组也可以嵌套,例如图像组中有三个子组;