I'm using python kivy. I want to display cards containing a title and underneath an image, in a grid with 5 columns.
The behavior of the following snippet is 90% of what I want. The images always fit the same space, leaving empty space up/down or left/right, so they maintain aspect ratio. The only problem is that all the rows are scaled to fit the window. I want the height of the space where the image should fit to be a custom percentage of the window height, and to scroll down and up to see the rows that don't fit the current window.
class MyApp(App):
def build(self):
scroll_view = ScrollView(do_scroll_x=False, do_scroll_y=True, smooth_scroll_end=15, scroll_wheel_distance=20, size=(Window.width, Window.height))
grid = GridLayout(cols=5, size_hint_x=1)
index = 0
for uuid, record in records.items():
image_texture = image_cache.get_image(uuid)
card = BoxLayout(orientation='vertical')
card.add_widget(Button(
text=record.name,
size_hint=(1, 0.2), # Stretch to fit column width (1 means full width)
on_press=lambda x: print(f"Button pressed: {x.text}")
))
card.add_widget(Image(
texture=image_texture,
size_hint_x=1,
))
grid.add_widget(card)
index += 1
if index >= 20:
break
scroll_view.add_widget(grid)
return scroll_view
if __name__ == '__main__':
MyApp().run()
I'm using python kivy. I want to display cards containing a title and underneath an image, in a grid with 5 columns.
The behavior of the following snippet is 90% of what I want. The images always fit the same space, leaving empty space up/down or left/right, so they maintain aspect ratio. The only problem is that all the rows are scaled to fit the window. I want the height of the space where the image should fit to be a custom percentage of the window height, and to scroll down and up to see the rows that don't fit the current window.
class MyApp(App):
def build(self):
scroll_view = ScrollView(do_scroll_x=False, do_scroll_y=True, smooth_scroll_end=15, scroll_wheel_distance=20, size=(Window.width, Window.height))
grid = GridLayout(cols=5, size_hint_x=1)
index = 0
for uuid, record in records.items():
image_texture = image_cache.get_image(uuid)
card = BoxLayout(orientation='vertical')
card.add_widget(Button(
text=record.name,
size_hint=(1, 0.2), # Stretch to fit column width (1 means full width)
on_press=lambda x: print(f"Button pressed: {x.text}")
))
card.add_widget(Image(
texture=image_texture,
size_hint_x=1,
))
grid.add_widget(card)
index += 1
if index >= 20:
break
scroll_view.add_widget(grid)
return scroll_view
if __name__ == '__main__':
MyApp().run()
You can set the height of the ScrollView
by using size_hint_y
.
Here is a similar App
that does what I think you want:
from kivy.app import App
from kivy.clock import Clock
from kivy.lang import Builder
from kivy.properties import StringProperty, ObjectProperty
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.image import Image
kv = '''
ScrollView:
size_hint_y: 0.75 # custom percentage of the window height
do_scroll_x: False
do_scroll_y: True
smooth_scroll_end: 15
scroll_wheel_distance: 20
GridLayout:
id: grid
cols: 5
spacing: 1, 5
size_hint: 1, None
height: self.minimum_height # must be allowed to grow for ScrollView to work
<Card>:
orientation: 'vertical'
size_hint: 1, None
height: 150 # must have a specified height for minimum_height to work in GridLayout
Button:
text: root.text
on_press: print(f"Button pressed: {self.text}")
size_hint_y: 0.25
Image:
texture: root.texture
size_hint_y: 0.75
'''
class Card(BoxLayout):
text = StringProperty('')
texture = ObjectProperty(None)
class MyApp(App):
def build(self):
Clock.schedule_once(self.fill_grid)
return Builder.load_string(kv)
def fill_grid(self, _dt):
grid = self.root.ids.grid
texture = Image(source='tester.png').texture
for index in range(50):
grid.add_widget(Card(text='record #' + str(index), texture=texture))
if __name__ == '__main__':
MyApp().run()