me2 beats
me2 beats

Reputation: 824

Kivy Bing images layout

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

Answers (1)

John Anderson
John Anderson

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

Related Questions