QML仿手机时间滚筒控件

QML仿手机时间滚筒控件

注意里面的图片使用自己的图片代替
使用自己封装的TimePathView.qml、TimePathItem.qml 控件
###\效果图

DatePage
这里写图片描述
####使用代码

    DatePage {
        id: datePage
        anchors.fill: parent
        show: true
        showPropertyChangesY:0
        hidePropertyChangesY:0
        onReturnPage:{
            if(ok){
                var currentDate = new Date()
                var hour = currentDate.getHours();
                var minute = currentDate.getMinutes();
                console.log(year,month,day,hour,minute);
            }
        }
    }

TimePage
这里写图片描述
####使用代码

    TimePage {
        id: timePage
        anchors.fill: parent
        show: true
        showPropertyChangesY:0
        hidePropertyChangesY:0
        hourModel24: true//24小时制度
        onReturnPage:{
            if(ok){
                var currentDate = new Date()
                var year = currentDate.getFullYear();
                var month = currentDate.getMonth();
                var day = currentDate.getDate();
                console.log(year,month+1,day,hour,minute);
            }
        }
    }

####实现代码 DatePage.qml

import QtQuick 2.0

import "qrc:/common/util.js" as Util
import "qrc:/common/"
import "qrc:/timeControl/"

AnimationItem {
    id:root

    property int  dateModelIndex : 0
    property int monthMaxDay : 30
    property int year: 0
    property int month: 0
    property int day: 0
    property int lockday: 0

    property string textColor:"white"
    property string highlightColor:"#0099ff"
    property int fontSize:30

    signal returnPage(bool ok)

    Rectangle{
        anchors.fill: parent
        color:"#000000"
        opacity:0.6//透明度为0.5
    }

    onYearChanged: {
        monthMaxDay = currentMonthMaxDay(year,month)
    }
    onMonthChanged: {
//        lockday = day;
//        dayPathView.initIndex = lockday -1;
        monthMaxDay = currentMonthMaxDay(year,month)
    }

    TimePathView{
        id:yearPathView
        anchors.horizontalCenter: parent.horizontalCenter
        anchors.horizontalCenterOffset: -200
        y:100
        width:200
        height:300
        order:true
        orderStartNum: 1970
        initIndex:year - 1970
        unitText:Util.lang(qsTr("年"))
        unitLeftMargin:-50
        model:130//yearModel
        onValueChanged: {
            year = value
        }
    }
    TimePathView{
        id:monthPathView
        anchors.horizontalCenter: parent.horizontalCenter
       // anchors.horizontalCenterOffset: 100
        y:100
        width:200
        height:300
        order:true
        orderStartNum: 1
        initIndex:month - 1
        unitText: Util.lang(qsTr("月"))
        unitLeftMargin:-70
        model:12
        onValueChanged: {
            month = value
        }

    }
    TimePathView{
        id:dayPathView
        anchors.horizontalCenter: parent.horizontalCenter
        anchors.horizontalCenterOffset: 200
        y:100
        width:200
        height:300
        order:true
        orderStartNum: 1
        initIndex:day - 1
        unitText:Util.lang(qsTr("日"))
        unitLeftMargin:-70
        model:
        monthMaxDay ===28?28:
        monthMaxDay ===29?29:
        monthMaxDay ===30?30:
        monthMaxDay ===31?31:0

        onValueChanged: {
            day = value
        }
    }

    //---按钮
    Row{
        id:timeSettingColumn

        anchors.top: dayPathView.bottom
        anchors.horizontalCenter: parent.horizontalCenter
        anchors.topMargin: 20
        spacing: 100

        Button{
            id:btnTime
            text:Util.lang(qsTr("确定"))
            pressedSource:  Util.fromTheme("Settings/setting_choose2.png")
            normalSource: Util.fromTheme("Settings/setting_choose.png")
            onClicked: {
                returnPage(true)
            }
        }
        Button{
            id:btnDate
            text:Util.lang(qsTr("取消"))
            pressedSource:  Util.fromTheme("Settings/setting_choose2.png")
            normalSource: Util.fromTheme("Settings/setting_choose.png")
            onClicked: {
               returnPage(false)
            }
        }
    }

//    //--初始化
    onShowChanged:  {
        if(show)
        {
            initTime()
            monthMaxDay = currentMonthMaxDay(year,month)
        }
    }

    function initTime(){
        var date = new Date;
        year = date.getFullYear()
        month = date.getMonth()+1
        day = date.getDate()

    }

    //--判断是否闰年
    function isLeapYear(year){
        var leap = false
        if(year%400==0||year%4==0&&year%100!=0)
            leap = true //是闰年
        else
            leap = false //不是闰年
        //console.log(year,"is leap year:",leap)
        return leap
    }

    //--判断大小月,2月不在判断范围内
    function isBigMonth(month){
        var bigMonth = false
        if(month !==4&&month !==6&&month !==9&&month !==11){
            bigMonth = true
        }else{
            bigMonth = false
        }
        //console.log("month is bigMonth:",bigMonth)
        return bigMonth
    }

    //--依据年、月判断最大日
    function currentMonthMaxDay(year,month){
        //是否2月?(闰年29,非闰28):(小月?30天:31天)
        var maxDay = 0
        if(month === 2){
            if(isLeapYear(year)){
                maxDay = 29
            }else{
                maxDay = 28
            }
        }else{
            if(isBigMonth(month)){
                maxDay = 31
            } else {
                maxDay = 30
            }
        }
        return maxDay
    }

}

####实现代码 TimePage.qml

import QtQuick 2.0

import "qrc:/common/util.js" as Util
import "qrc:/common/"
import "qrc:/timeControl/"


AnimationItem {
    id:root

    property bool  isAm:hour<12 //am pm
    property bool  hourModel24 : true
    property int hour: 0
    property int minute: 0
    property string textColor:"white"
    property string highlightColor:"#0099ff"
    property int fontSize:30

    signal returnPage(bool ok)

    Rectangle
    {
        anchors.fill: parent
        color:"#000000"
        opacity:0.6//透明度为0.5
    }

    Button{
        id:btntimeModel
        visible: !hourModel24
        anchors{
            verticalCenter: parent.verticalCenter
            verticalCenterOffset: -20
            horizontalCenter: parent.horizontalCenter
            horizontalCenterOffset: -300
        }

        text: isAm?Util.lang(qsTr("上午")):
                   Util.lang(qsTr("下午"))
        pressedSource:  Util.fromTheme("Settings/setting_choose2.png")
        normalSource: Util.fromTheme("Settings/setting_choose.png")
        onClicked: {
            // hour : 1 - 24
            var isAmValue =!isAm?0:1;
            hour = hourModel24?hour:(hour%12+isAmValue*12)
        }
    }

    TimePathView{
        id:hourPathView
        anchors.horizontalCenter: parent.horizontalCenter
        anchors.horizontalCenterOffset: -100
        y:100
        width:200
        height:300
        order:true
        orderStartNum: hourModel24?0:1
        initIndex: hourModel24?hour:(hour%12!==0?(hour%12 - 1):11)
        unitText: Util.lang(qsTr("时"))
        unitLeftMargin:-70
        model:  hourModel24?24:12
        onValueChanged: {
            var isAmValue =isAm?0:1;
            hour = hourModel24?value:(value%12+isAmValue*12)
        }
    }
    TimePathView{
        id:minutePathView
        anchors.horizontalCenter: parent.horizontalCenter
        anchors.horizontalCenterOffset: 100
        y:100
        width:200
        height:300
        order:true
        orderStartNum: 0
        initIndex:minute
        unitText: Util.lang(qsTr("分"))
        unitLeftMargin:-70
        model:60
        onValueChanged: {
            minute = value
        }
    }

    //---按钮
    Row{
        id:timeSettingColumn
        anchors.top: hourPathView.bottom
        anchors.horizontalCenter: parent.horizontalCenter
        anchors.topMargin: 30
        spacing: 100

        Button{
            id:btnTime
            text: Util.lang(qsTr("确定"))
            pressedSource:  Util.fromTheme("Settings/setting_choose2.png")
            normalSource: Util.fromTheme("Settings/setting_choose.png")
            onClicked: {
                returnPage(true);
            }
        }
        Button{
            id:btnDate
            text: Util.lang(qsTr("取消"))
            pressedSource:  Util.fromTheme("Settings/setting_choose2.png")
            normalSource: Util.fromTheme("Settings/setting_choose.png")
            onClicked: {
               returnPage(false)
            }
        }
    }

    onShowChanged:  {
        if(show)
        {
            initTime()
        }
    }

    function fix(num) {
        if ( num < 10) {
            return "0" + num;
        }else{
            return num;
        }
    }
    //初始化时间,控件跟随时间变化
    function initTime(){
        var currentDate = new Date()
        hour = currentDate.getHours()
        minute = currentDate.getMinutes()
        console.log(currentDate)

    }

}

###TimePathView.qml 代码如下

import QtQuick 2.0

Item {
    id: root

    property bool order: false//数字顺序列表
    property int orderStartNum: 1

    property int initIndex:0

    property alias model: myPathView.model
    property alias count: myPathView.count
    property alias unitText:unit.text

    signal valueChanged(var index,var value)

    property int fontSize:30
    property string textColor:"white"
    property string highlightColor:"#0099ff"
    property int unitLeftMargin:-50

    PathView{
        id:myPathView
        anchors.fill: parent
        currentIndex:initIndex
        delegate:TimePathItem{
            width:root.width/2
            height:root.height/myPathView.pathItemCount
            onSelected: {
                //--执行内部算法,寻找最短路径(时间开销依据处理器性能)
                //--在此过程中 currentIndex 值不确定,不可以用作处理
                myPathView.currentIndex = index

                //--发出信号
                var outValue = order?orderStartNum+index:
                                      myPathView.model[index];
                valueChanged(index,outValue);
            }
        }

        pathItemCount: 5;
        preferredHighlightBegin: 0.5;
        preferredHighlightEnd: 0.5;
        highlightRangeMode: PathView.StrictlyEnforceRange;

        //交互属性,支持拖动等……
        interactive: true
        //滑动速度
        maximumFlickVelocity:1000

        onMovementEnded: {
            //--发出信号
            //console.log("Math.cos(1/4) = "+Math.cos(1/4));
            var outValue = order?orderStartNum+myPathView.currentIndex:
                                  myPathView.model[myPathView.currentIndex];
            valueChanged(myPathView.currentIndex,outValue)
            //console.log("onMovementEnded ",myPathView.currentIndex)
            positionViewAtIndex(myPathView.currentIndex, PathView.Center)
        }

        path :pathVertical

        Path{//------------垂直变化------------
            id:pathVertical
            property int height: root.height
            startX: root.width/2

            PathLine { x: pathVertical.startX; y: pathVertical.startY; }
            PathAttribute { name: "iconZ"; value: 1 }
            PathAttribute { name: "iconScale"; value: 0.6 }
            PathAttribute { name: "iconOpacity"; value: 0.3 }
            PathAttribute { name: "iconAngle"; value: 80  }
            PathPercent { value: 0 }

            // start scaling up
            PathLine { x: pathVertical.startX; y: pathVertical.startY+ pathVertical.height * Math.cos(1/4); }
            PathAttribute { name: "iconZ"; value: 2 }
            PathAttribute { name: "iconScale"; value: 0.8 }
            PathAttribute { name: "iconOpacity"; value: 0.4 }
            PathAttribute { name: "iconAngle"; value: 50  }
            PathPercent { value: 1/8 }

            // middle point
            PathLine {
                x: pathVertical.startX;
                y: pathVertical.startY + pathVertical.height * Math.cos(1/4) ; }
            PathAttribute { name: "iconZ"; value: 5 }
            PathAttribute { name: "iconScale"; value: 1.0 }
            PathAttribute { name: "iconOpacity"; value:1.0 }
            PathAttribute { name: "iconAngle"; value: 0  }
            PathPercent { value: 4/8}

            // start scaling down
            PathLine { x:pathVertical.startX; y: pathVertical.startY + pathVertical.height *Math.cos(1/4); }
            PathAttribute { name: "iconZ"; value: 2 }
            PathAttribute { name: "iconScale"; value: 0.8}
            PathAttribute { name: "iconOpacity"; value: 0.4 }
            PathAttribute { name: "iconAngle"; value: -50  }
            PathPercent { value: 7/8 }

            // last point
            PathLine { x:  pathVertical.startX; y: pathVertical.startY + pathVertical.height*Math.cos(1/4); }
            PathAttribute { name: "iconZ"; value: 1 }
            PathAttribute { name: "iconScale"; value: 0.6 }
            PathAttribute { name: "iconOpacity"; value:0.3 }
            PathAttribute { name: "iconAngle"; value: -80  }
            PathPercent { value: 1}
            }

    }//PathView

    Text{
        id:unit
        anchors.verticalCenter: myPathView.verticalCenter
        anchors.verticalCenterOffset: -5
        anchors.left: myPathView.right
        anchors.leftMargin:unitLeftMargin
        //text:qsTr("年")
        verticalAlignment: Text.AlignVCenter
        font.pixelSize: 30
        color:highlightColor
    }


}

###TimePathItem.qml 代码如下

import QtQuick 2.0

import "qrc:/common/util.js" as Util
import "qrc:/common/"
import "qrc:/timeControl/"
Item{//
    id:root

    scale: PathView.iconScale!==undefined?PathView.iconScale:1
    opacity: PathView.iconOpacity!==undefined?PathView.iconOpacity:1
    z:PathView.iconZ!==undefined?PathView.iconZ:1

    signal selected(int index);

    transform: Rotation {
        id: rotation

        origin.x: root.width/2
        origin.y: root.height/2
        axis.x: 1
        axis.y: 0
        axis.z: 0
        angle: root.PathView.iconAngle!==undefined?root.PathView.iconAngle:0
    }

    Text{
        id:timeText
        anchors.centerIn: parent
        text:order?Number(modelData)+orderStartNum:modelData
        verticalAlignment: Text.AlignVCenter
        font.pixelSize: 30
        color: root.PathView.isCurrentItem ? highlightColor : textColor
    }

    MouseArea{
        id:itemMouseArea
        anchors.fill: parent

        onClicked: {
            root.selected(index)
        }
    }

}//Item

  • 2
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 11
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 11
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值