1. 程式人生 > 其它 >QML 自定義 Loading 樣式

QML 自定義 Loading 樣式

技術標籤:QML 三言兩語QMLLoadingBusyIndicator

QML 自帶的 BusyIndicator 自定義效果不大理響,所以自己做了兩個。效果如下:

程式碼連結:https://github.com/gongjianbo/QmlComponentStyle

實現程式碼:

import QtQuick 2.12
import QtQuick.Controls 2.12

//自定義 loading 效果
//龔建波 2021-1-17
Item {
    id: control

    //item圓圈個數
    property int itemCount: 10
    //item圓圈直徑大小
    property int itemSize: 16
    //item變大範圍
    property int itemExpand: 10
    //item圓圈顏色
    property color itemColor: "green"
    //當前item,配合動畫
    property int itemIndex: 0
    //輪轉一次的時長
    property int duration: 1500
    //
    property bool running: visible

    implicitHeight: 160
    implicitWidth: 160

    //index從0到count輪轉,轉到對應item就變大且不透明
    //animation也可以換成timer
    NumberAnimation{
        target: control
        property: "itemIndex"
        from: 0
        to: control.itemCount-1
        loops: Animation.Infinite
        duration: control.duration
        running: control.running
    }

    //加一層item.margin來容納item大小變化
    Item{
        id: content
        anchors.fill: parent
        anchors.margins: control.itemExpand/2+1

        Repeater{
            id: repeater
            model: control.itemCount
            Rectangle{
                id: item
                height: control.itemSize
                width: height
                x: content.width/2 - width/2
                y: content.height/2 - height/2
                radius: height/2
                color: control.itemColor

                //環繞在中心
                transform: [
                    Translate {
                        y: content.height/2-height/2
                    },
                    Rotation {
                        angle: index / repeater.count * 360
                        origin.x: width/2
                        origin.y: height/2
                    }
                ]

                //輪轉到當前item時就切換狀態
                state: control.itemIndex===index?"current":"normal"
                states: [
                    State {
                        name: "current"
                        PropertyChanges {
                            target: item
                            opacity: 1
                            height: control.itemSize+control.itemExpand
                        }
                    },
                    State {
                        name: "normal"
                        PropertyChanges {
                            target: item
                            opacity: 0.1
                            height: control.itemSize
                        }
                    }
                ]

                //大小和透明度的狀態過渡
                transitions: [
                    Transition {
                        from: "current"
                        to: "normal"
                        NumberAnimation{
                            properties: "opacity,height"
                            duration: control.duration
                        }
                    },
                    Transition {
                        from: "normal"
                        to: "current"
                        NumberAnimation{
                            properties: "opacity,height"
                            duration: 0
                        }
                    }
                ]
            }
        }
    }
}
import QtQuick 2.12
import QtQuick.Controls 2.12

//自定義 loading 效果
//目前角度是設定死的,可以根據直徑算
//龔建波 2021-1-17
Item {
    id: control

    //item圓圈個數
    property int itemCount: 4
    //item圓圈直徑
    property int itemSize: 20
    //item圓圈顏色
    property color itemColor: "green"
    //轉一次時長
    property int duration: 3000
    //
    property bool running: visible

    implicitHeight: 160
    implicitWidth: 160

    Item{
        id: content
        anchors.fill: parent
        anchors.margins: 5

        Repeater{
            id: repeater
            model: control.itemCount

            //長方形wrapper用來旋轉
            Item{
                id: wrapper
                width: control.itemSize
                height: content.height
                x: content.width/2-width/2
                //todo 目前角度是設定死的,可以根據直徑算
                rotation: -index*20

                //動畫序列,根據順序做了間隔
                SequentialAnimation {
                    running: control.running
                    loops: Animation.Infinite
                    NumberAnimation{
                        duration: index*100
                    }
                    ParallelAnimation{
                        RotationAnimation{
                            target: wrapper
                            from: -index*20
                            to: 360-index*20
                            duration: control.duration
                            easing.type: Easing.OutCubic
                        }
                        SequentialAnimation{
                            NumberAnimation{
                                target: item
                                property: "opacity"
                                from: 0
                                to: 1
                                duration: control.duration*1/8
                            }
                            NumberAnimation{
                                duration: control.duration*3/4
                            }
                        }
                    }
                    NumberAnimation{
                        duration: (control.itemCount-index)*100
                    }
                }

                //小圓圈
                Rectangle{
                    id: item
                    height: control.itemSize
                    width: height
                    radius: height/2
                    color: control.itemColor
                }
            }
        }
    }
}