QML用PathView实现一个轮播图

轮播图是一个常见的功能,在QML中,可以使用PathView来实现一个循环播放的轮播图组件。

默认情况,如果限制了加载个数,切换时第一帧会马上消失,第二帧才进入,这样会有断档的感觉。通过设置PathView中preferredHighlightBegin/End为0.5,这样当前选定的项位于路径的中间,就没有断档的感觉了。效果如下(为了测试,我没有clip,clip之后只有范围内的才可见):

//CircleView.qml

import QtQuick 2.12
import QtQuick.Controls 2.12

//轮播图
Item {
    id: control

    property int indicatorWidth: 12

    //定时切换间隔
    property alias timerInterval: path_timer.interval
    //切换动画执行时间
    property alias pathDuration: path_view.highlightMoveDuration
    property alias delegate: path_view.delegate
    property alias model: path_view.model
    //页数
    property alias count: path_page.count

    PathView{
        id: path_view
        anchors.fill: parent

        //此属性保存任何时候在路径上可见的项目数。
        //将pathItemCount设置为undefined将显示路径上的所有项目。
        //因为path代码的问题,设置为2最合适
        pathItemCount: 2

        //测试时,把clip去掉就能看到完整的
        //clip: true

        //向前移动,即顺序0 1 2 3
        movementDirection: PathView.Positive

        //切换的时间
        highlightMoveDuration: 1000

        //视图中突出显示(当前项目)的首选范围,默认值PathView.StrictlyEnforceRange
        //配合preferredHighlight的范围0.5 0.5,就能显示在正中,切换更自然
        //highlightRangeMode: PathView.StrictlyEnforceRange

        //希望当前选定的项位于路径的中间,则将突出显示范围设置为0.5,0.5
        preferredHighlightBegin: 0.5
        preferredHighlightEnd: 0.5
        path: Path {
            startX: -path_view.width/2
            startY: path_view.height / 2

            PathLine {
                x: path_view.pathItemCount * path_view.width-path_view.width / 2
                y: path_view.height / 2
            }
        }
        onModelChanged: {
            if(path_timer.running){
                path_timer.restart();
            }
        }

        //测试用
        //model: ["red","green","blue"]
        //delegate: Rectangle{
        //    width: path_view.width
        //    height: path_view.height
        //    color: modelData
        //}
    }
    //定时切换
    Timer{
        id: path_timer
        running: control.visible
        repeat: true
        interval: 3000
        onTriggered: {
            //至少两个才切换
            if(path_view.count>1)
                path_view.currentIndex=(path_view.currentIndex+1)%path_view.count
        }
    }
    //右下角小圆圈
    PageIndicator {
        id: path_page
        anchors{
            right: parent.right
            bottom: parent.bottom
            margins: 30
        }
        count: path_view.count
        currentIndex: path_view.currentIndex
        spacing: control.indicatorWidth
        delegate: Rectangle{
            width: control.indicatorWidth
            height: width
            radius: width/2
            color: "white"
            //非当前页就灰色
            opacity: index===path_page.currentIndex?1:0.6
            Behavior on opacity {
                OpacityAnimator{
                    duration: 200
                }
            }
            //点击跳转到该页
            //还有问题,非连续的item,他会快速连续切换到目标index
            //因为不是直接切换,有闪烁的感觉
            MouseArea{
                anchors.fill: parent
                onClicked: {
                    path_view.currentIndex=index;
                    if(path_timer.running){
                        path_timer.restart();
                    }
                }
            }
        }
    }
}

//main.qml  

测试了不同的Item个数

import QtQuick 2.12
import QtQuick.Window 2.12
import QtQuick.Controls 2.12

Window {
    visible: true
    width: 700
    height: 500
    title: qsTr("龚建波 1992")

    color: "#021B39"

    Column{
        anchors.centerIn: parent
        spacing: 10
        CircleView{
            width: 100
            height: 50
            model:["red","green","blue","orange"]

            delegate: Rectangle {
                width: 100
                height: 50
                color: modelData
                //Component.onCompleted: console.log(modelData,"completed")
            }

            Rectangle{
                anchors.fill: parent
                color: "transparent"
                border.color: "white"
            }
        }
        CircleView{
            width: 100
            height: 50
            model:["red","green","blue"]

            delegate: Rectangle {
                width: 100
                height: 50
                color: modelData
                //Component.onCompleted: console.log(modelData,"completed")
            }

            Rectangle{
                anchors.fill: parent
                color: "transparent"
                border.color: "white"
            }
        }
        CircleView{
            width: 100
            height: 50
            model:["red","green"]

            delegate: Rectangle {
                width: 100
                height: 50
                color: modelData
                //Component.onCompleted: console.log(modelData,"completed")
            }

            Rectangle{
                anchors.fill: parent
                color: "transparent"
                border.color: "white"
            }
        }
        CircleView{
            width: 100
            height: 50
            model:["red"]

            delegate: Rectangle {
                width: 100
                height: 50
                color: modelData
                //Component.onCompleted: console.log(modelData,"completed")
            }

            Rectangle{
                anchors.fill: parent
                color: "transparent"
                border.color: "white"
            }
        }
        CircleView{
            width: 100
            height: 50

            delegate: Rectangle {
                width: 100
                height: 50
                color: modelData
                //Component.onCompleted: console.log(modelData,"completed")
            }

            Rectangle{
                anchors.fill: parent
                color: "transparent"
                border.color: "white"
            }
        }
    }
}

借鉴:https://github.com/lowbees/CirCleView.git

发布了95 篇原创文章 · 获赞 26 · 访问量 12万+

猜你喜欢

转载自blog.csdn.net/gongjianbo1992/article/details/103517663