Skip to content

Instantly share code, notes, and snippets.

@tshirtman
Last active June 16, 2022 01:39
Show Gist options
  • Save tshirtman/908d299846b5195f27fb9ae1ab78d4ba to your computer and use it in GitHub Desktop.
Save tshirtman/908d299846b5195f27fb9ae1ab78d4ba to your computer and use it in GitHub Desktop.
use a proxy widget to animate items of a recycleview without leaking on other widgets.
from copy import copy
from kivy.app import App
from kivy.clock import triggered
from kivy.lang import Builder
from kivy.animation import Animation
from kivy.factory import Factory as F
from kivy.properties import (
ObjectProperty, ListProperty
)
KV = '''
<Item>:
index: None
animation_proxy: None
on_release: app.animate_item(self.index)
RecycleView:
data: app.data
viewclass: 'Item'
RecycleBoxLayout:
orientation: 'vertical'
size_hint: 1, None
height: self.minimum_height
default_size_hint: 1, None
default_size: 0, dp(40)
'''
class Item(F.Button):
animation_proxy = ObjectProperty(allownone=True)
_animation_proxy = None
def update_opacity(self, proxy, opacity):
self.opacity = opacity
def on_animation_proxy(self, *args):
if self._animation_proxy:
self._animation_proxy.unbind(opacity=self.update_opacity)
self._animation_proxy = self.animation_proxy
if self.animation_proxy:
self.opacity = self.animation_proxy.opacity
self.animation_proxy.bind(opacity=self.update_opacity)
else:
self.opacity = 1
class Application(App):
data = ListProperty()
def build(self):
self.data = [
{'index': i, 'text': 'hello {}'.format(i), 'animation_proxy': None}
for i in range(1000)
]
return Builder.load_string(KV)
def update_time(self, dt):
self.time += dt
@triggered(timeout=0.05)
def animate_item(self, index):
proxy = F.Widget(opacity=1)
item = copy(self.data[index])
animation = (
Animation(opacity=0, d=.1, t='out_quad')
+ Animation(opacity=1, d=5, t='out_quad')
)
animation.bind(on_complete=lambda *x: self.reset_animation(item))
item['animation_proxy'] = proxy
self.data[index] = item
animation.start(proxy)
def reset_animation(self, item):
# animation is complete, widget should be collected
item['animation_proxy'] = None
if __name__ == "__main__":
Application().run()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment