• 【QML Model-View】ListView-动画+上移下移(三)


    ListView 提供了 add、remove、move、populate、displaced 几种场景的过渡动画效果,你 可以通过设置相应的属性来改变特定场景对应的过渡动画。这些场景对应的属性,类型都是 Transition,—个场景也可能有多个属性,比如新增 Item 会触发 add 过渡动画,同时也可能引 起其他 Item 的位置变化,进而触发 addDisplaced 或 displaced 过渡动画。

    效果

    初始化 动画

    ListView 第一次初始化使用 populate 动画:

    // 在ListView第一次实例化或者因Model变化而需要创建Item时应用
    populate: Transition {
        NumberAnimation {
            property: "opacity"
            from: 0
            to: 1.0
            duration: 1000
        }
    }
    

    这将产生一个渐显效果。

    add 动画

    add 属性指定向 ListView 新增一个 Item 时针对该 Item 应用的过渡动画。其设置了一个 ParallelAnimation,内含一个变换透明度的动画和一个变换 y 位置的动画。

    // add过渡动画(新增Item触发)
    add: Transition {
        ParallelAnimation{
            NumberAnimation {
                property: "opacity"
                from: 0
                to: 1.0
                duration: 1000
            }
            NumberAnimation {
                properties: "x,y"
                from: 0
                duration: 1000
            }
        }
    }
    

    最终的效果是,新增 Item 从 ListView 上方渐现、缓缓下落到特定位置。 需要注意的是,尽量不要在 add 动画中改变 Item 的高度,因为这样会引起它下面的其他 Item 被重新布局进而错放位置,也会带来性能上的损耗。

    displaced 动画

    我点击 “Insert” 按钮时,新增 Item 下方的那些被迫移位的 Item,没有明显的动画效果。 这是因为 displaced 属性默认为 null,ListView 没有提供默认的移位动画。

    displaced 属性用于指定通用的、由于 Model 变化导致 Item 被迫移位时的动画效果,而相应 的 addDisplaced、moveDisplaced、removeDisplaced 则用于指定由特定的 add、move、remove 操作引起的移位动画。如果你同时指定了 displaced 和 xxxDisplaced,那 xxxDisplaced生效;如果你只指定 displaced,那只要有移位发生,displaced 动画就会被应用。

    // 用于指定通用的、由于Model变化导致Item被迫移位时的动画效果
    displaced: Transition {
        SpringAnimation {
            property: "y"
            spring: 3
            damping: 0.1
            epsilon: 0.25
        }
    }
    

    再运行看看,点击 “Insert” 按钮,会发现位于新增 Item 下方的那些 Item 会向下移动,来回弹几次才平静下来。

    remove 动画

    remove 属性指定将一个 Item 从 ListView 中移除时应用的过渡动画。当动画开始执行时, Item 已经被移除,此时任何对该 Item 的引用都是非法的。移除一个 Item 可能会导致其他 Item 移位,此时会触发 removeDisplaced 或 displaced 过渡动画。给 ListView 指定 remove 动画如下:

    // remove过渡动画(移除Item触发)
    remove: Transition {
        SequentialAnimation{
            NumberAnimation {
                properties: "y"
                to: 0
                duration: 600
            }            
            NumberAnimation {
                property: "opacity"
                to: 0
                duration: 400
            }
        }
    }
    

    再运行看看,双击一个 Item,它会先移动到 ListView 顶部,然后再慢慢变得看不见。

    move 动画

    move 属性指定移动一个 Item 时要应用的过渡动画。

    // move过渡动画(移动Item触发)
    move: Transition {
        NumberAnimation {
            property: "y"
            duration: 700
            easing.type: Easing.InQuart
        }
    }
    

    上移 + 下移

    我们以之前的示例为基础,构造一个专门演示动画效果的示例,phone_list_animation. qml。我给 footer 添加了 Up 和 Down 按钮,还增加了 moveUp 和 moveDown 信号,连接到 ListView 新增的 moveUp() 和 moveDown() 方法上。新的 footer 组件定义如下:

    // 定义footer
    Component {
        id: footerView
    
        Item{
            id: footerRootItem
             parent.width
            height: 30
    
            // 自定义信号
            signal add()
            signal insert()
            signal moveUp()
            signal moveDown()
    
            // 新增按钮
            Button {
                id: addOne
                anchors.right: parent.right
                anchors.rightMargin: 4
                anchors.verticalCenter: parent.verticalCenter
                text: "Add"
                onClicked: footerRootItem.add()
            }
    
            // 插入按钮
            Button {
                id: insertOne
                anchors.right: addOne.left
                anchors.rightMargin: 4
                anchors.verticalCenter: parent.verticalCenter
                text: "Insert"
                onClicked: footerRootItem.insert()
            }
    
            // 下移按钮
            Button {
                id: moveDown;
                anchors.right: insertOne.left
                anchors.rightMargin: 4
                anchors.verticalCenter: parent.verticalCenter
                text: "Down"
                onClicked: footerRootItem.moveDown()
            }
    
            // 上移按钮
            Button {
                id: moveUp;
                anchors.right: moveDown.left
                anchors.rightMargin: 4
                anchors.verticalCenter: parent.verticalCenter
                text: "Up"
                onClicked: footerRootItem.moveUp()
            }
        }
    }
    

    ListView 新增 moveUp() 和 moveDown() 方法,计算当前 Item 的索引,调用 model 的 move() 方法让当前 Item 下移一个位置。给 move 属性设置了一个 Transition 对象。新的 ListView 声明如下:

        // 定义ListView
        ListView {
            id: listView
            anchors.fill: parent
            interactive: false
    
            delegate: phoneDelegate
            model: phoneModel.createObject(listView)
            header: headerView
            footer: footerView
            focus: true
            highlight: Rectangle{
                color: "lightblue"
            }
            
            // 在ListView第一次实例化或者因Model变化而需要创建Item时应用
            populate: Transition {
                NumberAnimation {
                    property: "opacity"
                    from: 0
                    to: 1.0
                    duration: 1000
                }
            }
    
            // add过渡动画(新增Item触发)
            add: Transition {
                ParallelAnimation{
                    NumberAnimation {
                        property: "opacity"
                        from: 0
                        to: 1.0
                        duration: 1000
                    }
                    NumberAnimation {
                        properties: "x,y"
                        from: 0
                        duration: 1000
                    }
                }
            }
            
            // 用于指定通用的、由于Model变化导致Item被迫移位时的动画效果
            displaced: Transition {
                SpringAnimation {
                    property: "y"
                    spring: 3
                    damping: 0.1
                    epsilon: 0.25
                }
            }
            
            // remove过渡动画(移除Item触发)
            remove: Transition {
                SequentialAnimation{
                    NumberAnimation {
                        properties: "y"
                        to: 0
                        duration: 600
                    }            
                    NumberAnimation {
                        property: "opacity"
                        to: 0
                        duration: 400
                    }
                }
            }
            
            // move过渡动画(移动Item触发)
            move: Transition {
                NumberAnimation {
                    property: "y"
                    duration: 700
                    easing.type: Easing.InQuart
                }
            }
            
            // 新增函数
            function addOne() {
                model.append(
                            {
                                "name": "MX3",
                                "cost": "1799",
                                "manufacturer": "MeiZu"
                            } 
                )
            }
            
            // 插入函数
            function insertOne() {
                model.insert( Math.round(Math.random() * model.count),
                            {
                                "name": "HTC One E8",
                                "cost": "2999",
                                "manufacturer": "HTC"
                            } 
                )
            }
            
            // 上移函数
            function moveUp() {
                if(currentIndex - 1 >= 0){
                    model.move(currentIndex, currentIndex - 1, 1)
                }
            }
    
            // 下移函数
            function moveDown() {
                if(currentIndex + 1 < model.count){
                    model.move(currentIndex, currentIndex + 1, 1)
                }
            }
            
            // 连接信号槽
            Component.onCompleted: {
                listView.footerItem.add.connect(listView.addOne)
                listView.footerItem.insert.connect(listView.insertOne)
                listView.footerItem.moveUp.connect(listView.moveUp)
                listView.footerItem.moveDown.connect(listView.moveDown)
            }      
        }
    }
    

    现在可以执行 “qmlscenephone_list_animation.qml” 看看效果了。

    下载链接

    全部代码下载链接:https://github.com/confidentFeng/QML_Demo/tree/master/ListViewPhone


    参考:

    《Qt Quick核心编程》第13章


  • 相关阅读:
    欧拉公式
    isap的一些想法
    错误合集
    Hello World
    PAT (Advanced Level) Practice 1068 Find More Coins
    PAT (Advanced Level) 1087 All Roads Lead to Rome
    PAT (Advanced Level) 1075 PAT Judge
    PAT (Advanced Level) 1067 Sort with Swap(0, i)
    PAT (Advanced Level) 1017 Queueing at Bank
    PAT (Advanced Level) 1025 PAT Ranking
  • 原文地址:https://www.cnblogs.com/linuxAndMcu/p/13597128.html
Copyright © 2020-2023  润新知