How to create Dropdown animation in Kivy
Question:
I’m trying to animate a dropdown symbol to rotate down (when the dropdown option is open) and revert back to it’s original position (when dropdown option closes). Please find this attached screenshot.
Here’s my py file:
from kivy.lang.builder import Builder
from kivymd.app import MDApp
from kivy.uix.screenmanager import Screen, ScreenManager
from kivy.utils import get_color_from_hex as hex
from kivy.animation import Animation
Builder.load_file("dropdowns_and_btns.kv")
kv = """
#:import hex kivy.utils.get_color_from_hex
#:import FadeTransition kivy.uix.screenmanager.FadeTransition
MyScreenManager:
transition: FadeTransition(duration=0)
IntroPage:
LandingPage:
ResultPage:
<IntroPage>
MDScreen:
md_bg_color: hex("#07074D")
MDLabel:
text: "BGF"
color: hex("#ECE4F5")
font_size: 36
pos_hint: {"center": (0.5, 0.7)}
halign: "center"
RoundedGradientButton:
text: "START"
font_size: 20
size_hint: 0.3, 0.08
pos_hint: {"center": (0.5, 0.3)}
on_release: app.root.current = "landing_page"
<LandingPage>
name: "landing_page"
MDScreen:
md_bg_color: hex("#07074D")
MDLabel:
icon_color: 1, 0, 1, 1
text: "Please select"
pos_hint: {"center_y": 0.9}
halign: "center"
font_size: 32
color: hex("#ECE4F5")
# Dropdown Label
MDFloatLayout:
size_hint: 0.75, 0.3
pos_hint: {"center": (0.5, 0.5)}
BoxLayout
size_hint: 0.5, 0.9
pos_hint: {"center": (0.26, 0.9)}
MDLabel:
text: "Month"
color: hex("#ECE4F5")
BoxLayout
size_hint: 0.5, 0.9
pos_hint: {"center": (0.79, 0.9)}
MDLabel:
text: "Year"
color: hex("#ECE4F5")
# Dropdown Button
MDGridLayout:
cols: 2
size_hint: 1, 0.3
pos_hint: {"center": (0.5, 0.65)}
spacing: 30
DropdownMenu:
id: month
text: 'Select'
values: [month for month, x in app.temp_db.items()]
on_text: self.text
DropdownMenu:
id: year
text: 'Select'
values: [f"{year}" for year in range(18, 46)]
on_text: self.text
# Find now button
RoundedGradientButton:
text: "FIND NOW"
font_size: 16
size_hint: 0.25, 0.25
pos_hint: {"center": (0.5, 0.15)}
<ResultPage>
name: "result_page"
MDScreen:
md_bg_color: hex("#07074D")
MDLabel:
id: result_prefix_label
text: "Congratulations!"
color: hex("#ECE4F5")
font_size: 20
pos_hint: {"center": (0.5, 0.7)}
halign: "center"
MDLabel:
id: result_label
color: hex("#ECE4F5")
font_size: 40
pos_hint: {"center": (0.5, 0.6)}
halign: "center"
Button:
background_normal: ""
background_color: 0, 0, 0, 0
pos_hint: {"center": (0.5, 0.3)}
on_press: app.root.current = "landing_page"
Image:
source: "images/reload.png"
center_x: self.parent.center_x
center_y: self.parent.center_y
size_hint_x: None
height: 50
"""
class IntroPage(Screen):
pass
class LandingPage(Screen):
pass
class ResultPage(Screen):
pass
class MyScreenManager(ScreenManager):
pass
class BabyGenderFinder(MDApp):
temp_db = {"January": 1, "February": 2, "March": 3, "April": 4, "May": 5}
def build(self):
return Builder.load_string(kv)
def DropdownBtnAnimation(self, wid):
ani = Animation(angle=-90, duration=0.02)
ani.start(wid)
BabyGenderFinder().run()
kv file:
#:import hex kivy.utils.get_color_from_hex
#:import Factory kivy.factory.Factory
# Drop down button setting
<DropdownMenu@Spinner>
dropdown_cls: Factory.CustomDropdown
option_cls: Factory.DropdownOptions
color: hex("#87828C")
font_name: "fonts/Poppins-Medium.ttf"
background_normal: ""
background_color: 0, 0, 0, 0
on_release: self.color = hex("ECE4F5") ; app.DropdownBtnAnimation(self.ids.dropdown_sign)
canvas.before:
Color:
rgba: hex("#111140")
RoundedRectangle:
size: self.size
pos: self.pos
radius: [6]
Color:
rgba: hex("#1F1F73")
Line:
width: 1.25
rounded_rectangle: self.x, self.y, self.width, self.height, 6, 6, 6, 6, 100
MDIconButton:
id: dropdown_sign
center_x: self.parent.center_x + 110
center_y: self.parent.center_y
angle: 0
canvas.before:
PushMatrix
Rotate:
angle: self.angle
axis: 0, 0, 1
origin: self.center
canvas.after:
PopMatrix
Image:
source: "images/dropdown.png"
size_hint: None, None
size: 20, 20
# Drop down options setting
<DropdownOptions@SpinnerOption>
color: hex("#ECE4F5")
font_name: "fonts/Poppins-Regular.ttf"
background_normal: ""
background_color: 0, 0, 0, 0
# Drop down options separator setting
canvas:
Color:
rgba: hex("#3D3D99")
Line:
width: 1
points: self.x+10, self.y, self.width-10, self.y
<CustomDropdown@DropDown>:
canvas.before:
Color:
rgba: hex("#1F1F73")
RoundedRectangle:
size: self.size
pos: self.pos
radius: [0, 0, 6, 6]
max_height: 200
# Gradient button settings
<RoundedGradientButton@Button>
background_normal: ""
background_color: 0,0,0,0
font_name: "fonts/Poppins-Medium.ttf"
on_press: self.size_hint = self.size_hint_x/1.05, self.size_hint_y/1.05
on_release: self.size_hint = self.size_hint_x*1.05, self.size_hint_y*1.05
canvas.before:
Color:
rgba: 1, 1, 1, 1
RoundedRectangle:
source: "button_bg.png"
size: self.size
pos: self.pos
radius: [self.size[1]/1.92]
I can make the button rotate down, but I can’t seem to make the button go back to normal when dropdown options closes. I also want some actions done when I close Spinner widget (ex: If I clicked outside the dropdown options list when the list is open, I wanna trigger some actions)
I’m fairly new with kivy. Please help me.
Answers:
In your kv
, you can set the angle
back to 0
when the text
is changed on the DropdownMenu
:
DropdownMenu:
id: month
text: 'Select'
values: [month for month, x in app.temp_db.items()]
on_text: self.ids.dropdown_sign.angle=0
Or, you can eliminate the animation completely, and just set the angle of the icon to depend on whether the DropdownMenu
is open:
MDIconButton:
id: dropdown_sign
center_x: self.parent.center_x + 110
center_y: self.parent.center_y
# angle: 0
canvas.before:
PushMatrix
Rotate:
angle: 90 if root.is_open else 0 # adjusts angle of icon
axis: 0, 0, 1
origin: self.center
canvas.after:
PopMatrix
Image:
source: "images/dropdown.png"
size_hint: None, None
size: 20, 20
I’m trying to animate a dropdown symbol to rotate down (when the dropdown option is open) and revert back to it’s original position (when dropdown option closes). Please find this attached screenshot.
Here’s my py file:
from kivy.lang.builder import Builder
from kivymd.app import MDApp
from kivy.uix.screenmanager import Screen, ScreenManager
from kivy.utils import get_color_from_hex as hex
from kivy.animation import Animation
Builder.load_file("dropdowns_and_btns.kv")
kv = """
#:import hex kivy.utils.get_color_from_hex
#:import FadeTransition kivy.uix.screenmanager.FadeTransition
MyScreenManager:
transition: FadeTransition(duration=0)
IntroPage:
LandingPage:
ResultPage:
<IntroPage>
MDScreen:
md_bg_color: hex("#07074D")
MDLabel:
text: "BGF"
color: hex("#ECE4F5")
font_size: 36
pos_hint: {"center": (0.5, 0.7)}
halign: "center"
RoundedGradientButton:
text: "START"
font_size: 20
size_hint: 0.3, 0.08
pos_hint: {"center": (0.5, 0.3)}
on_release: app.root.current = "landing_page"
<LandingPage>
name: "landing_page"
MDScreen:
md_bg_color: hex("#07074D")
MDLabel:
icon_color: 1, 0, 1, 1
text: "Please select"
pos_hint: {"center_y": 0.9}
halign: "center"
font_size: 32
color: hex("#ECE4F5")
# Dropdown Label
MDFloatLayout:
size_hint: 0.75, 0.3
pos_hint: {"center": (0.5, 0.5)}
BoxLayout
size_hint: 0.5, 0.9
pos_hint: {"center": (0.26, 0.9)}
MDLabel:
text: "Month"
color: hex("#ECE4F5")
BoxLayout
size_hint: 0.5, 0.9
pos_hint: {"center": (0.79, 0.9)}
MDLabel:
text: "Year"
color: hex("#ECE4F5")
# Dropdown Button
MDGridLayout:
cols: 2
size_hint: 1, 0.3
pos_hint: {"center": (0.5, 0.65)}
spacing: 30
DropdownMenu:
id: month
text: 'Select'
values: [month for month, x in app.temp_db.items()]
on_text: self.text
DropdownMenu:
id: year
text: 'Select'
values: [f"{year}" for year in range(18, 46)]
on_text: self.text
# Find now button
RoundedGradientButton:
text: "FIND NOW"
font_size: 16
size_hint: 0.25, 0.25
pos_hint: {"center": (0.5, 0.15)}
<ResultPage>
name: "result_page"
MDScreen:
md_bg_color: hex("#07074D")
MDLabel:
id: result_prefix_label
text: "Congratulations!"
color: hex("#ECE4F5")
font_size: 20
pos_hint: {"center": (0.5, 0.7)}
halign: "center"
MDLabel:
id: result_label
color: hex("#ECE4F5")
font_size: 40
pos_hint: {"center": (0.5, 0.6)}
halign: "center"
Button:
background_normal: ""
background_color: 0, 0, 0, 0
pos_hint: {"center": (0.5, 0.3)}
on_press: app.root.current = "landing_page"
Image:
source: "images/reload.png"
center_x: self.parent.center_x
center_y: self.parent.center_y
size_hint_x: None
height: 50
"""
class IntroPage(Screen):
pass
class LandingPage(Screen):
pass
class ResultPage(Screen):
pass
class MyScreenManager(ScreenManager):
pass
class BabyGenderFinder(MDApp):
temp_db = {"January": 1, "February": 2, "March": 3, "April": 4, "May": 5}
def build(self):
return Builder.load_string(kv)
def DropdownBtnAnimation(self, wid):
ani = Animation(angle=-90, duration=0.02)
ani.start(wid)
BabyGenderFinder().run()
kv file:
#:import hex kivy.utils.get_color_from_hex
#:import Factory kivy.factory.Factory
# Drop down button setting
<DropdownMenu@Spinner>
dropdown_cls: Factory.CustomDropdown
option_cls: Factory.DropdownOptions
color: hex("#87828C")
font_name: "fonts/Poppins-Medium.ttf"
background_normal: ""
background_color: 0, 0, 0, 0
on_release: self.color = hex("ECE4F5") ; app.DropdownBtnAnimation(self.ids.dropdown_sign)
canvas.before:
Color:
rgba: hex("#111140")
RoundedRectangle:
size: self.size
pos: self.pos
radius: [6]
Color:
rgba: hex("#1F1F73")
Line:
width: 1.25
rounded_rectangle: self.x, self.y, self.width, self.height, 6, 6, 6, 6, 100
MDIconButton:
id: dropdown_sign
center_x: self.parent.center_x + 110
center_y: self.parent.center_y
angle: 0
canvas.before:
PushMatrix
Rotate:
angle: self.angle
axis: 0, 0, 1
origin: self.center
canvas.after:
PopMatrix
Image:
source: "images/dropdown.png"
size_hint: None, None
size: 20, 20
# Drop down options setting
<DropdownOptions@SpinnerOption>
color: hex("#ECE4F5")
font_name: "fonts/Poppins-Regular.ttf"
background_normal: ""
background_color: 0, 0, 0, 0
# Drop down options separator setting
canvas:
Color:
rgba: hex("#3D3D99")
Line:
width: 1
points: self.x+10, self.y, self.width-10, self.y
<CustomDropdown@DropDown>:
canvas.before:
Color:
rgba: hex("#1F1F73")
RoundedRectangle:
size: self.size
pos: self.pos
radius: [0, 0, 6, 6]
max_height: 200
# Gradient button settings
<RoundedGradientButton@Button>
background_normal: ""
background_color: 0,0,0,0
font_name: "fonts/Poppins-Medium.ttf"
on_press: self.size_hint = self.size_hint_x/1.05, self.size_hint_y/1.05
on_release: self.size_hint = self.size_hint_x*1.05, self.size_hint_y*1.05
canvas.before:
Color:
rgba: 1, 1, 1, 1
RoundedRectangle:
source: "button_bg.png"
size: self.size
pos: self.pos
radius: [self.size[1]/1.92]
I can make the button rotate down, but I can’t seem to make the button go back to normal when dropdown options closes. I also want some actions done when I close Spinner widget (ex: If I clicked outside the dropdown options list when the list is open, I wanna trigger some actions)
I’m fairly new with kivy. Please help me.
In your kv
, you can set the angle
back to 0
when the text
is changed on the DropdownMenu
:
DropdownMenu:
id: month
text: 'Select'
values: [month for month, x in app.temp_db.items()]
on_text: self.ids.dropdown_sign.angle=0
Or, you can eliminate the animation completely, and just set the angle of the icon to depend on whether the DropdownMenu
is open:
MDIconButton:
id: dropdown_sign
center_x: self.parent.center_x + 110
center_y: self.parent.center_y
# angle: 0
canvas.before:
PushMatrix
Rotate:
angle: 90 if root.is_open else 0 # adjusts angle of icon
axis: 0, 0, 1
origin: self.center
canvas.after:
PopMatrix
Image:
source: "images/dropdown.png"
size_hint: None, None
size: 20, 20