QML中的进入和离开动画
Enter and Leave animation in QML
在我的 qml 应用程序中有内容区域 "Item" 并且它有一个 "loader" 用于加载 qml 文件。
我想实现进出动画效果
例如,当我将源设置为其他 qml 文件时(second.qml),我当前的加载器源是 "First.qml"。 "First.qml" 应该淡出,"second.qml" 会淡入。
我该如何实现?
我尝试了以下代码,它只为 second.qml 设置动画。当我们设置源时 "first.qml" 消失。我也想给初始 qml 一个淡出动画 ("first.qml")
Loader{
id:contentLoader
source: "First.qml"
onSourceChanged: animation.running = true
NumberAnimation {
id: animation
target: contentLoader.item
property: "opacity"
from: 0
to: 1
duration: 1000
easing.type: Easing.bezierCurve
}
}
//button click
Button{
text:modelData
width:100
height: parent.height
onClicked: {
contentLoader.setSource("Second.qml")
}
}
好的,所以我认为您有两个主要选择..
1) 使用 SequentialAnimation 淡出第一个视图,加载第二个视图,然后用类似...
的方式淡入
SequentialAnimation {
id: switchContentAnimation
//Fade out first view
NumberAnimation {
target: contentLoader
property: "opacity"
duration: 1000
from: 0
to: 1
}
//Switch view
ScriptAction { script: contentLoader.setSource("Second.qml"); }
//Fade new view back in
NumberAnimation {
target: contentLoader
property: "opacity"
duration: 1000
from: 0
to: 1
}
}
此方法会导致该区域在几分之一秒内为空白。而第二种选择是..
2) 通过添加第二个 Loader 来交叉淡入淡出,然后当您 select 按钮时,您会在不透明度上交叉淡入淡出。这可能看起来像..
property bool activeView: false //false: first, true: second
Loader{
id:contentLoaderOne
source: "First.qml"
onOpacityChanged: {
if(opacity == 0) {
//unload this loaders source to save memory
}
}
}
Loader{
id:contentLoaderTwo
onOpacityChanged: {
if(opacity == 0) {
//unload this loaders source to save memory
}
}
}
ParallelAnimation {
id: switchContentAnimation
NumberAnimation {
target: contentLoaderOne
properties: "opacity"
duration: 1000
to: (activeView) ? 1 : 0
}
NumberAnimation {
target: contentLoaderTwo
properties: "opacity"
duration: 1000
to: (!activeView) ? 1 : 0
}
}
//button click
Button{
text:modelData
width:100
height: parent.height
onClicked: {
if(activeView) {
//switch to second view..
contentLoaderTwo.setSource("Second.qml")
}
else {
//switch back to first view..
contentLoaderOne.setSource("First.qml")
}
activeView = !activeView;
switchContentAnimation.start()
}
}
这里可能有错误,因为现在无法 运行 代码!
另一种方法是使用 StackView
,因为它支持自定义动画。
使用它的 replace
功能,您可以更改显示的项目。
import QtQuick 2.9
import QtQuick.Controls 2.2
ApplicationWindow {
id : root
title: qsTr("Hello World")
width: 640
height: 480
visible:true
Component {
id: lightblueRectangleComponent
Rectangle {
color: "lightblue"
Button {
anchors.centerIn: parent
text: "replace"
onClicked: stackView.replace(orangeRectangleComponent)
}
}
}
Component {
id: orangeRectangleComponent
Rectangle {
color: "orange"
Button {
anchors.centerIn: parent
text: "replace"
onClicked: stackView.replace(lightblueRectangleComponent)
}
}
}
StackView {
id: stackView
anchors.fill: parent
initialItem: lightblueRectangleComponent
replaceEnter: Transition {
PropertyAnimation {
property: "opacity"
from: 0
to:1
duration: 200
easing.type: Easing.OutQuad
}
}
replaceExit: Transition {
PropertyAnimation {
property: "opacity"
from: 1
to:0
duration: 200
easing.type: Easing.InQuad
}
}
}
}
在我的 qml 应用程序中有内容区域 "Item" 并且它有一个 "loader" 用于加载 qml 文件。
我想实现进出动画效果
例如,当我将源设置为其他 qml 文件时(second.qml),我当前的加载器源是 "First.qml"。 "First.qml" 应该淡出,"second.qml" 会淡入。
我该如何实现?
我尝试了以下代码,它只为 second.qml 设置动画。当我们设置源时 "first.qml" 消失。我也想给初始 qml 一个淡出动画 ("first.qml")
Loader{
id:contentLoader
source: "First.qml"
onSourceChanged: animation.running = true
NumberAnimation {
id: animation
target: contentLoader.item
property: "opacity"
from: 0
to: 1
duration: 1000
easing.type: Easing.bezierCurve
}
}
//button click
Button{
text:modelData
width:100
height: parent.height
onClicked: {
contentLoader.setSource("Second.qml")
}
}
好的,所以我认为您有两个主要选择..
1) 使用 SequentialAnimation 淡出第一个视图,加载第二个视图,然后用类似...
的方式淡入SequentialAnimation {
id: switchContentAnimation
//Fade out first view
NumberAnimation {
target: contentLoader
property: "opacity"
duration: 1000
from: 0
to: 1
}
//Switch view
ScriptAction { script: contentLoader.setSource("Second.qml"); }
//Fade new view back in
NumberAnimation {
target: contentLoader
property: "opacity"
duration: 1000
from: 0
to: 1
}
}
此方法会导致该区域在几分之一秒内为空白。而第二种选择是..
2) 通过添加第二个 Loader 来交叉淡入淡出,然后当您 select 按钮时,您会在不透明度上交叉淡入淡出。这可能看起来像..
property bool activeView: false //false: first, true: second
Loader{
id:contentLoaderOne
source: "First.qml"
onOpacityChanged: {
if(opacity == 0) {
//unload this loaders source to save memory
}
}
}
Loader{
id:contentLoaderTwo
onOpacityChanged: {
if(opacity == 0) {
//unload this loaders source to save memory
}
}
}
ParallelAnimation {
id: switchContentAnimation
NumberAnimation {
target: contentLoaderOne
properties: "opacity"
duration: 1000
to: (activeView) ? 1 : 0
}
NumberAnimation {
target: contentLoaderTwo
properties: "opacity"
duration: 1000
to: (!activeView) ? 1 : 0
}
}
//button click
Button{
text:modelData
width:100
height: parent.height
onClicked: {
if(activeView) {
//switch to second view..
contentLoaderTwo.setSource("Second.qml")
}
else {
//switch back to first view..
contentLoaderOne.setSource("First.qml")
}
activeView = !activeView;
switchContentAnimation.start()
}
}
这里可能有错误,因为现在无法 运行 代码!
另一种方法是使用 StackView
,因为它支持自定义动画。
使用它的 replace
功能,您可以更改显示的项目。
import QtQuick 2.9
import QtQuick.Controls 2.2
ApplicationWindow {
id : root
title: qsTr("Hello World")
width: 640
height: 480
visible:true
Component {
id: lightblueRectangleComponent
Rectangle {
color: "lightblue"
Button {
anchors.centerIn: parent
text: "replace"
onClicked: stackView.replace(orangeRectangleComponent)
}
}
}
Component {
id: orangeRectangleComponent
Rectangle {
color: "orange"
Button {
anchors.centerIn: parent
text: "replace"
onClicked: stackView.replace(lightblueRectangleComponent)
}
}
}
StackView {
id: stackView
anchors.fill: parent
initialItem: lightblueRectangleComponent
replaceEnter: Transition {
PropertyAnimation {
property: "opacity"
from: 0
to:1
duration: 200
easing.type: Easing.OutQuad
}
}
replaceExit: Transition {
PropertyAnimation {
property: "opacity"
from: 1
to:0
duration: 200
easing.type: Easing.InQuad
}
}
}
}