I'm trying to create a scrollable popup window dynamically in kivy (without a kv file). My goal is two things.
Have the popup window scroll if the popup_label has to much text
Make the popup_label text wrap and use its own space without overflowing onto other widgets if the text is too large.
The problem:
I've been trying many variations of the below code but i can't get the popup to scroll. As you can see from the screen shot attached, i've got text starting to go outside the top of the popup window and big spaces between widgets and when viewed on the phone the white popup_label text is all bunched together and overflowing over the blue header labels.
Any advice please ? PS: I'm self taught in python and kivy and it's my first app so please respond with understandable lingo :) IE: x - y for x in x / cos(*%s , %d) will go over my head :)
snippet of relevant code so far :
class LocationPopupMenu(Popup):
"""
Add a popup dialog box when a user clicks an employers location pin
This is called from "EmployerMarker.py
"""
def __init__(self, user_data):
self.user = user_data
super().__init__()
root = App.get_running_app()
regotype = root.registration_type
measurement = root.firebase_user['measurement']
# Set all the required fields of current_user data
# Update this list with matching data you want to add to the popup
if regotype == "Employer":
headers = "Preferred Catagories : ,Preferred Positions : ,Distance Away : "
else:
headers = "Hiring Catagories : ,Positions : ,Distance Away : "
headers = headers.split(',')
# Generate a Gridlayout for the popup
layout = GridLayout(cols=1, padding=5, spacing=5, size_hint_y=None)
# attempt to bind like i would in a kv file IE : height: self.minimum_height
layout.bind(minimum_height=layout.setter("height"))
scrollLayout = ScrollView(orientation='vertical', scroll_type=['content'])
layout.add_widget(scrollLayout)
closeButton = None
attribute_value = ""
for i in range(len(headers)):
# iterate over the attributes of the current_user
attribute_name = headers[i]
if i == 0:
attribute_value = user_data['position_categories']
if i == 1:
attribute_value = user_data['position_sub_categories']
if i == 2:
attribute_value = f"{user_data['distance']} {measurement}"
# Add the attributes to a label then add the label widget to the layout
# add the blue header labels
popup_header = MDLabel(text=f"{attribute_name}", font_size="22sp", text_size=(self.width, None), halign="left", valign="center", size_hint_y=None, theme_text_color="Custom", text_color=root.theme_cls.accent_color)
popup_header.bind(height=popup_header.setter("texture_size"))
# Add the white labels
popup_label = MDLabel(text=f"{attribute_value}", font_size="22sp", text_size=(self.width, None), halign="left", valign="top", size_hint_y=None)
# attempt to bind texture_size as i would for kv file IE: height: self.texture_size[1] ?
# so that if popup_label is a large amount of text it doesnt just display over the top of
# other widgets, it displays inside its own allocated grid
popup_label.bind(height=popup_label.setter("texture_size"))
layout.add_widget(popup_header)
layout.add_widget(popup_label)
# Add a button to the bottom of the popup
closeButton = MDRoundFlatButton(text="Close me", opposite_colors=True, font_size="17sp", halign="center", valign="center", size_hint_y=None, height="40dp", opacity=1, line_color=root.theme_cls.primary_dark, text_color="yellow", on_release=self.dismiss)
profileButton = MDRoundFlatButton(text="View Profile", opposite_colors=True, font_size="17sp", halign="center", valign="center", size_hint_y=None, height="40dp", opacity=1, line_color=root.theme_cls.primary_dark, text_color=root.theme_cls.accent_color, on_release=self.viewProfile)
if regotype == "Employer":
layout.add_widget(profileButton)
layout.add_widget(closeButton)
# set the attributes to the popup class
setattr(self, "title", f"{user_data['registration_type']} Details")
setattr(self, "content", layout)
setattr(self, "auto_dismiss", False)
and the screenshot when run on linux screen shot of popup window
The problem is that you are adding the ScrollView
to the GridLayout
. It should be the opposite. Try changing:
layout.add_widget(scrollLayout)
to:
scrollLayout.add_widget(layout)
and change:
setattr(self, "content", layout)
to:
setattr(self, "content", scrollLayout)
or:
self.content = scrollLayout