2

I'm using QtQuick/QML and I want to create a ripple effect when I click on a button. I do know that this is available in Material Style, but I think it's an inherent property when you change the theme and I don't want to change anything else in my project.

Is there a way to add ONLY the ripple effect onto my button, and change nothing else? If so, how do I do it?

eyllanesc
  • 235,170
  • 19
  • 170
  • 241
Shravan
  • 75
  • 1
  • 1
  • 10
  • This is available "hidden" in `import QtQuick.Controls.Material.impl 2.3`, look in your Qt installation folder in the qml folder for some inspiration how to use it – Amfasis May 31 '20 at 06:26
  • 1
    I would use `RadialGradient` for the background and some `Animation` to make the effect. – folibis May 31 '20 at 06:59

4 Answers4

1

As Kostia Hvorov said, QtQuick.Controls.Material.impl.Ripple is the easiest way to go. I would like to add my trick to handle rectangular background with radius:

import QtQuick 2.12
import QtQuick.Controls 2.12
import QtQuick.Controls.Material.impl 2.12
import QtGraphicalEffects 1.12

Column
{
    spacing: 20
    
    Button
    {
        anchors.horizontalCenter: parent.horizontalCenter
        id: button
        text: "ripple demo"
    }
    
    Ripple {
        id: ripple
        anchors.horizontalCenter: parent.horizontalCenter
        clipRadius: 4
        width: 200
        height: 64
        pressed: button.pressed
        active: button.down || button.visualFocus || button.hovered
        color: "#20FFFFFF"
        layer.enabled: true
        layer.effect: OpacityMask {
            maskSource: Rectangle
            {
                width: ripple.width
                height: ripple.height
                radius: 4
            }
        }
    }
}   

Try it Online

  • When I try to use Ripple, I am told that it is an unknown component. If I try to import QtQuick.Controls.Material.impl, I am told it cannot be found. – James Hudson Mar 02 '21 at 21:48
0

Easiest way to do it - using Ripple from QtQuick.Controls.Material.impl

So just add Ripple to your background Rect:

Ripple {
    clipRadius: height
    width: parent.width
    height: parent.height
    pressed: control.pressed
    anchor: control
    active: control.down || control.visualFocus || control.hovered
    color: control.flat && control.highlighted ?  control.Material.highlightedRippleColor : control.Material.rippleColor
}

You can replace "control.Material.rippleColor" or/and "control.Material.highlightedRippleColor" to any color and get any ripple color effect.

But there is one problem, it will work only with rectangular background(without round) otherwise it will be looking bad.

0

Using QtQuick 2, I have made this with some PropertyAnimation. Here is how:

import QtQuick 2.15
import QtQuick.Controls 2.15

Button {
    id: control

    opacity: enabled ? 1.0 : 0.2

    property int tripleWidth: width * 3

    background: Rectangle {
        border.width: 1
        border.color: "black"
        radius: 3
        color: "white"

        clip: true

        Rectangle {
            id: ripple
            property int diameter: 0
            property int pressX: 0
            property int pressY: 0

            x: pressX - radius
            y: pressY - radius

            color: "green"
            radius: diameter / 2
            width: diameter
            height: diameter

            opacity: 1 - diameter / control.tripleWidth

            function animate(x, y, size) {
                pressX = x
                pressY = y
                diameter = size
            }

            Behavior on diameter {
                PropertyAnimation {
                    duration: 200
                    onRunningChanged: {
                        if(!running) {
                            duration = 0;
                            ripple.diameter = 0;
                            duration = 200;
                        }
                    }
                }
            }
        }
    }

    onClicked: {
        ripple.animate(pressX, pressY, control.tripleWidth)
    }

    contentItem: Item {
        implicitWidth: txt.implicitWidth
        implicitHeight: 20

        Text {
            id: txt
            anchors.centerIn: parent
            text: control.text
        }
    }
}
Ponzifex
  • 555
  • 5
  • 20
0

I Edit last Answer and its work.. Here is How:

import QtQuick 2.5
import QtQuick.Window 2.5
import QtQuick.Controls 2.5

RoundButton {
    id: control
    width: 93
    height: 39

    property int tripleWidth: width * 3

    background: Rectangle {
        border.width: 1
        border.color: "black"
        radius: 3
        color: "white"

        clip: true

        Rectangle {
            id: ripple
            property int diameter: 0
            property int pressX: 0
            property int pressY: 0

            x: pressX - radius
            y: pressY - radius

            color: "green"
            radius: diameter / 2
            width: diameter
            height: diameter

            opacity: 1

            function animate(x, y, size) {
                pressX = x
                pressY = y
                diameter = size
            }

            Behavior on diameter {
                PropertyAnimation {
                    duration: 300
                }
            }
        }
    }

    onHoveredChanged: {
        ripple.opacity = 0
        ripple.diameter = 0
    }

    onPressed: {
        ripple.opacity = 0.8
        ripple.animate(pressX, pressY, control.tripleWidth)
    }

    Timer {
        id: timer
    }

    contentItem: Item {
        implicitWidth: txt.implicitWidth
        implicitHeight: 20

        Text {
            id: txt
            font.pointSize: 15
            anchors.centerIn: parent
        }
    }

    onClicked: {
        function delay(delayTime, cb) {
                timer.interval = delayTime;
                timer.repeat = false;
                timer.triggered.connect(cb);
                timer.start();
            }
        delay(10, function() {
            ripple.opacity = 0
            ripple.diameter = 0
        })
    }
}

Try it....