Sean
Sean

Reputation: 79

How to use touchripple.py with Kivy lang?

I'm trying to create a button using touchripple.py found in kivy.uix.behaviors. However, I ended up unsuccessful. Can anyone show an easy example of touchripple with buttons using Kivy lang? Thanks in advance. Now, only the ripple effect isn't showing still. Please advice. Thanks.

In rippleexample2.py:

from kivy.app import App
from kivy.uix.touchripple import TouchRippleBehavior
from kivy.uix.button import Button
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.lang import Builder
from kivy.properties import (StringProperty, NumericProperty, ObjectProperty,
ListProperty, DictProperty, BooleanProperty)

class RippleButton(TouchRippleBehavior, Button):
    isRippled = BooleanProperty(False)

    def __init__(self, **kwargs):
        super(RippleButton, self).__init__(**kwargs)

    def on_touch_down(self, touch):
        collide_point = self.collide_point(touch.x, touch.y)
        if collide_point and not self.isRippled:
            self.isRippled = True
            self.ripple_show(touch)
        return super(RippleButton, self).on_touch_down(touch)

    def on_touch_up(self, touch):
        collide_point = self.collide_point(touch.x, touch.y)
        if collide_point and self.isRippled:
            self.isRippled = False
            self.ripple_fade()
        return super(RippleButton, self).on_touch_up(touch)

    def doit(self, *args):
        print('in doit')

 class Login(Screen):
    pass

class MainScreen(Screen):
    pass

class ScreenManager(ScreenManager):
    pass

MainScreen = Builder.load_file("rippleexample2.kv")

class SimpleKivy4(App):
    def build(self):
        return MainScreen

if __name__ == "__main__":
    SimpleKivy4().run()

In rippleexample2.kv:

ScreenManager:
    Login:
    MainScreen:

<Login>:
    name:"login"
    RippleButton:
        text:'Login'
        font_size: 24
        on_release: app.root.current = "main"


<MainScreen>:
    name: "main"
    RippleButton:
        text: 'back'
        on_release: app.root.current = "login"

Upvotes: 1

Views: 509

Answers (2)

ikolim
ikolim

Reputation: 16041

Below is a snippet for creating a Button which renders the touch ripple animation on interaction:

Snippet

class RippleButton(TouchRippleBehavior, Button):

    def on_touch_down(self, touch):
        collide_point = self.collide_point(touch.x, touch.y)
        if collide_point:
            touch.grab(self)

            # The background_color (r, g, b, a) of button widget defaults to [1, 1, 1, 1]
            # where 'a' (alpha compositing or transparency) is 1 i.e. not transparent

            self.transparency = self.background_color[3]    # backup original transparency / alpha compositing
            self.background_color[3] = 0.5  # set transparency to half (0.5)

            self.ripple_show(touch)

            # dispatch on_press event because we have consumed on_touch_down
            self.dispatch('on_press')

            # consumed touch down and don’t want it to propagate any further.
            return True
        return False

    def on_touch_up(self, touch):
        if touch.grab_current is self:
            touch.ungrab(self)
            self.ripple_fade()

            # defer on_release until ripple_fade has completed
            def defer_release(dt):
                self.background_color[3] = self.transparency  # restore transparency / alpha compositing
                self.dispatch('on_release')

            Clock.schedule_once(defer_release, self.ripple_duration_out)

            # consumed touch up and don’t want it to propagate any further.
            return True
        return False

Example

main.py

from kivy.app import App
from kivy.uix.behaviors.touchripple import TouchRippleBehavior
from kivy.uix.button import Button
from kivy.uix.screenmanager import Screen
from kivy.lang import Builder
from kivy.clock import Clock


class RippleButton(TouchRippleBehavior, Button):

    def on_touch_down(self, touch):
        collide_point = self.collide_point(touch.x, touch.y)
        if collide_point:
            touch.grab(self)

            # The background_color (r, g, b, a) of button widget defaults to [1, 1, 1, 1]
            # where 'a' (alpha compositing or transparency) is 1 i.e. not transparent

            self.transparency = self.background_color[3]    # backup original transparency / alpha compositing
            self.background_color[3] = 0.5  # set transparency to half (0.5)

            self.ripple_show(touch)

            # dispatch on_press event because we have consumed on_touch_down
            self.dispatch('on_press')

            # consumed touch down and don’t want it to propagate any further.
            return True
        return False

    def on_touch_up(self, touch):
        if touch.grab_current is self:
            touch.ungrab(self)
            self.ripple_fade()

            # defer on_release until ripple_fade has completed
            def defer_release(dt):
                self.background_color[3] = self.transparency  # restore transparency / alpha compositing
                self.dispatch('on_release')

            Clock.schedule_once(defer_release, self.ripple_duration_out)

            # consumed touch up and don’t want it to propagate any further.
            return True
        return False

    def doit(self, *args):
        print('in doit')


class Login(Screen):
    pass


class MainScreen(Screen):
    pass


class SimpleKivy4(App):
    def build(self):
        return Builder.load_file("main.kv")


if __name__ == "__main__":
    SimpleKivy4().run()

main.kv

#:kivy 1.11.0

ScreenManager:
    Login:
    MainScreen:

<Login>:
    name:"login"
    RippleButton:
        text:'Login'
        font_size: 24
        on_release: root.manager.current = "main"


<MainScreen>:
    name: "main"
    RippleButton:
        text: 'back'
        on_release: root.manager.current = "login"

Output

Kivy Touch Ripple Button

Upvotes: 1

John Anderson
John Anderson

Reputation: 39117

After looking a bit closer at the example, I noticed that they are doing some odd things in the RippleButton. They were stopping the dispatching of the touch events for some unknown reason. I have modified the code to continue the dispatching (so now the on_release should work). And I have added a BooleanProperty to keep track of whether the TouchRipple Behavior is in effect.

from kivy.app import App
from kivy.lang import Builder
from kivy.properties import BooleanProperty
from kivy.uix.behaviors import TouchRippleBehavior
from kivy.uix.button import Button


class RippleButton(TouchRippleBehavior, Button):
    isRippled = BooleanProperty(False)

    def __init__(self, **kwargs):
        super(RippleButton, self).__init__(**kwargs)

    def on_touch_down(self, touch):
        collide_point = self.collide_point(touch.x, touch.y)
        if collide_point and not self.isRippled:
            self.isRippled = True
            self.ripple_show(touch)
        return super(RippleButton, self).on_touch_down(touch)

    def on_touch_up(self, touch):
        collide_point = self.collide_point(touch.x, touch.y)
        if collide_point and self.isRippled:
            self.isRippled = False
            self.ripple_fade()
        return super(RippleButton, self).on_touch_up(touch)

    def doit(self, *args):
        print('in doit')

theRoot = Builder.load_string('''
RippleButton:
    text: 'Click Here'
    on_release: self.doit()
''')

class TouchRippleApp(App):
    def build(self):
        return theRoot

if __name__ == '__main__':
    TouchRippleApp().run()

Upvotes: 0

Related Questions