Qml 自定义滑动解锁条展示+源码分享

字体颜色变化参考: https://www.cnblogs.com/surfsky/p/4293117.html

一、废话

项目需要一个滑动解锁功能,本来以为qt有现成的控件可以用,但是找了半天没找到,网上也没作业抄,所以就动手写了一个。
分享给各位,如果对你有帮助请点个赞满足下小弟的虚荣心 ^-^谢谢。

二、效果

自动复位,很人性化
在这里插入图片描述

三、调用方法

hint :文字
sourceLock:锁定的图标
sourceUnlock:解锁的图标
输入大小、位置+以上3个参数就能正常用,

解锁后会发送unlock信号

UnlockSlider {
        id: unlockSlider
        anchors{top: parent.top; left: parent.left; margins: 150}
        hint: "滑动解锁"
        sourceLock: "qrc:/icon/suo-tianchong.png"
        sourceUnlock: "qrc:/icon/suo.png"
        onUnlock: {
            console.log("unlock")
            unlockSlider.visible = false
        }
    }

四、源码

注释比较随意,见谅~

import QtQuick 2.0
import QtGraphicalEffects 1.0
/**   铁头娃翻船了   2020.03.30   **/

Item {
    id: shell
    readonly property real visualPosition: brick.x / (width - brick.width)
    property string hint: "滑动解锁"
    property alias sourceLock: lockIcon.source
    property alias sourceUnlock: unlockIcon.source
    signal unlock

    implicitWidth: 400; implicitHeight: 70

    Rectangle{
        id: bg
        anchors.fill: parent
        radius: height * 0.5
        color: "white"
        opacity: 0.5
    }

    /****************   提示文字    ***************/
    Text{
        id: backText
        anchors.centerIn: parent
        opacity: 0.8
        text: hint
        font.pixelSize: shell.height * 0.5
        color: "gray"
    }
    Text{
        id: foreText
        visible: false
        anchors.centerIn: parent
        text: hint
        font.pixelSize: backText.font.pixelSize
        color: "white"
    }
    OpacityMask{
        anchors.centerIn: parent
        width: foreText.contentWidth; height: foreText.contentHeight
        source: foreText
        maskSource: maskArea
    }
    RadialGradient{     //创建一个透明度渐变的椭圆来做 OpacityMask 的mask
        id: maskArea
        visible: false
        width: foreText.contentWidth; height: foreText.contentHeight
        anchors.left: parent.left
        gradient: Gradient {
            GradientStop{position: 0.1; color: "red"}
            GradientStop{position: 0.8; color: "transparent"}
        }
    }
    PropertyAnimation{  //改变mask的水平偏移来使mask移动
       target: maskArea
       properties: 'horizontalOffset'
       from: -maskArea.width
       to: maskArea.width + maskArea.horizontalRadius
       duration: 2000
       running: true
       loops: -1
    }

    /***************   滑块    ***************/
    Item{
        id: brick
        width: parent.height * 0.8; height: width
        anchors.verticalCenter: parent.verticalCenter
        x: shell.height - height
        Rectangle{
            id: brickBg1
            anchors.fill: parent
            radius: height * 0.5
            color: "white"
            opacity: 1 - shell.visualPosition
        }
        Rectangle{
            id: brickBg2
            anchors.fill: parent
            radius: height * 0.5
            color: "lightgreen"
            opacity: shell.visualPosition
        }
        Image {
            id: lockIcon
            anchors.centerIn: parent
            source: ""
            sourceSize.height: parent.height * 0.7
            opacity: 1 - shell.visualPosition
        }
        Image {
            id: unlockIcon
            visible: visualPosition > 0.5
            anchors.centerIn: parent
            source: ""
            sourceSize.height: parent.height * 0.7
            opacity: shell.visualPosition > 0.5 ? 2*(shell.visualPosition-0.5): 0
        }
        MouseArea{
            id: mouseArea
            drag.target: brick
            drag.minimumX: 0; drag.maximumX: shell.width - width
            drag.minimumY: 0; drag.maximumY: 0
            anchors.fill: brick
            onReleased: {
                if(brick.x+brick.width < shell.width * 0.9){    //没触发
                    brick.x = shell.height - height
                }
                else {          //触发
                    brick.x = shell.width - width - (shell.height - height)
                    delayEmitTimer.start()
                }
            }
        }
        Behavior on x {
            PropertyAnimation {
                id: xAni
                duration: 200
            }
        }
        Timer{
            id: delayEmitTimer
            interval: xAni.duration + 150
            onTriggered: {
                delayEmitTimer.stop()
                shell.unlock()
                brick.x = shell.height - mouseArea.height   //触发后滑块复位
            }
        }
    }
    /***************   滑块终点    ***************/
    Rectangle{
        id: fantasy
        width: parent.height * 0.8; height: width
        radius: height * 0.5
        anchors.verticalCenter: parent.verticalCenter
        x: shell.width - width - (shell.height - height)
        color: "transparent"
        border{color: "lightgreen"; width: 1}
        opacity: shell.visualPosition > 0.5 ? 2*(shell.visualPosition-0.5): 0
        Image {
            visible: visualPosition > 0.5
            anchors.centerIn: parent
            source: unlockIcon.source
            sourceSize.height: parent.height * 0.7
            opacity: shell.visualPosition > 0.5 ? 2*(shell.visualPosition-0.5): 0
        }
    }
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值