Reputation: 824
I'm trying to make something like a "Bing images" layout.
That is:
I did not find a way to do this using Stack Layout, so I decided to create my own layout.
I stopped here:
from kivy.app import App
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.image import Image
from kivy.properties import NumericProperty
from kivy.lang import Builder
from kivy.core.window import Window
from kivy.uix.scrollview import ScrollView
KV = '''
#:import Window kivy.core.window.Window
ScrollView
size_hint: (1, None)
size: Window.size
MyLayout
id:my_l
Button
text:'1'
Button
size_hint_y: None
height: 900
text:'2'
Button
text:'3'
Button
text:'4'
Button
text:'5'
size_hint_y: None
height: 900
<MyLayout>:
#height: self.minimum_height
cols: 3
spacing: 10
size_hint_y:None
row_width: 300
'''
class MyLayout(FloatLayout):
def __init__(self, **kwargs):
super(MyLayout, self).__init__(**kwargs)
cols = NumericProperty(3)
row_width = NumericProperty(300)
spacing = NumericProperty(0)
def do_layout(self, *args):
self.i = 0
self.last_x = [self.height]*self.cols
for child in self.children[::-1]:
child.width = self.row_width
if isinstance(child, Image):
child.height = child.width / child.image_ratio
child.size_hint_y= None
child.size_hint_x= None
self.i+=1
if self.i == self.cols+1: self.i = 1
child.x = self.x+(self.i-1)*(self.row_width+self.spacing)
child.y = self.last_x[self.i-1]-child.height
self.last_x[self.i-1]-=child.height+self.spacing
def on_pos(self, *args):
self.do_layout()
def on_size(self, *args):
self.do_layout()
def add_widget(self, widget):
super(SuperGrid, self).add_widget(widget)
self.do_layout()
def remove_widget(self, widget):
super(SuperGrid, self).remove_widget(widget)
self.do_layout()
class MyApp(App):
def build(self):
self.root = Builder.load_string(KV)
Window.bind(on_dropfile=self.add)
def add(self, *args):
name= list(args)[1]
self.root.ids.my_l.add_widget(Image(source=name))
MyApp().run()
It is already partially working (you can run it and dragndrop some images from your folders to see what I'm about), but the problem is that I don't understand how to connect a ScrollView to it.
It looks like I need to add a line with something like height: self.minimum_height
to KV string.
but it’s not clear where in layout class I need to calculate minimum_height
.
How to make the code work with ScrollView?
Upvotes: 0
Views: 57
Reputation: 39092
You just need to calculate the height
of your MyLayout
instance. In your kv
file add:
size_hint: (1, None)
in your MyLayout
section
Then, in the do_layout
method, calculate the height
of your MyLayout
. Do a self.height =
just once at the end do_layout
(to avoid infinite loop due to on_size
method). For example here is a modified version of your do_layout
:
def do_layout(self, *args):
self.i = 0
col_heights = [0] * self.cols # keeps track of the height of each column
self.last_x = [self.height]*self.cols
for child in self.children[::-1]:
child.width = self.row_width
if isinstance(child, Image):
child.height = child.width / child.image_ratio
child.size_hint_y= None
child.size_hint_x= None
self.i+=1
if self.i == self.cols+1:
self.i = 1
col_heights[self.i-1] += child.height + self.spacing
child.x = self.x+(self.i-1)*(self.row_width+self.spacing)
child.y = self.last_x[self.i-1]-child.height
self.last_x[self.i-1]-=child.height+self.spacing
if len(self.children) > 0:
self.height = max(col_heights)
Upvotes: 1