Making a layout with variable number of columns per row in kivy?
Question: In kivy, what is the preferred way to make a screen that has a variable number
of columns per row? Is there a way to accomplish this without explicitly
specifying the positions and sizes of the widgets in a layout (i.e. is there a
way to do this as if you were stacking a bunch of GridLayouts with different
numbers of rows and cols within a Screen)? What is the way to do this using
only python code?

For instance, let's say you have a Screen which contain some type of Layout,
called "layout_scr1". How would you go about arranging things so that, for
example, the first row of layout_scr1 contains 1 column, the second row
contains 2 columns, and the third row contains 4 columns? Thank you.


Answer: There are quite a few options, but I think the simplest way would be using
`BoxLayout` instead of `GridLayout` or even `StackLayout`. `StackLayout` could
go to a second row the width is not enough whereas `BoxLayout` and
`GridLayout` stays on the same line. You can find and explanation of the
difference between `BoxLayout` and `GridLayout`
[here](http://stackoverflow.com/questions/18222194/kivy-boxlayout-vs-
gridlayout/18237038#18237038).

Here is the output:

![enter image description here](http://i.stack.imgur.com/6mSq8.png)

Here is the code:

    
    
    from kivy.app import App
    from kivy.lang import Builder
    from kivy.uix.floatlayout import FloatLayout
    
    Builder.load_string("""
    <Boxes>:
        AnchorLayout:
            anchor_x: 'center'
            anchor_y: 'top'
            ScreenManager:
                size_hint: 1, .9
                id: _screen_manager
                Screen:
                    name: 'screen1'
                    BoxLayout: 
                        orientation: 'vertical'
                        padding: 50
                        BoxLayout:
                            orientation: 'horizontal'
                            Button:
                                text: "1"
                        BoxLayout:
                            orientation: 'horizontal'
                            Button:
                                text: "2"
                            Button:
                                text: "3"
                            Button:
                                text: "4"
                        BoxLayout:
                            orientation: 'horizontal'
                            Button:
                                text: "5"
                            Button:
                                text: "6"
                        BoxLayout:
                            orientation: 'horizontal'
                            Button:
                                text: "7"
                            Button:
                                text: "8"
                            Button:
                                text: "9"
                            Button:
                                text: "10"
                Screen:
                    name: 'screen2'
                    Label: 
                        text: 'Another Screen'
        AnchorLayout:
            anchor_x: 'center'
            anchor_y: 'bottom'
            BoxLayout:
                orientation: 'horizontal'
                size_hint: 1, .1
                Button:
                    text: 'Go to Screen 1'
                    on_press: _screen_manager.current = 'screen1'
                Button:
                    text: 'Go to Screen 2'
                    on_press: _screen_manager.current = 'screen2'""")
    
    class Boxes(FloatLayout):
        pass
    
    class TestApp(App):
        def build(self):
            return Boxes()
    
    if __name__ == '__main__':
        TestApp().run()
    

If you still want to use `GridLayouts` you can substitute:

    
    
    BoxLayout: 
        orientation: 'vertical'
    

for this:

    
    
    GridLayout: 
        cols: 1
    

and this:

    
    
    BoxLayout: 
        orientation: 'vertical'
    

for this:

    
    
    GridLayout: 
        cols: 1
    

And just in case you were looking for a more dynamic approach:

    
    
    from kivy.app import App
    from kivy.lang import Builder
    from kivy.uix.floatlayout import FloatLayout
    from kivy.uix.boxlayout import BoxLayout
    from kivy.uix.button import Button
    
    Builder.load_string("""
    <Boxes>:
        boxes: _boxes 
        AnchorLayout:
            anchor_x: 'center'
            anchor_y: 'top'
            ScreenManager:
                size_hint: 1, .9
                id: _screen_manager
                Screen:
                    name: 'screen1'
                    BoxLayout: 
                        orientation: 'vertical'
                        padding: 50
                        id: _boxes
                Screen:
                    name: 'screen2'
                    Label: 
                        text: 'Another Screen'
        AnchorLayout:
            anchor_x: 'center'
            anchor_y: 'bottom'
            BoxLayout:
                orientation: 'horizontal'
                size_hint: 1, .1
                Button:
                    text: 'Go to Screen 1'
                    on_press: _screen_manager.current = 'screen1'
                Button:
                    text: 'Go to Screen 2'
                    on_press: _screen_manager.current = 'screen2'""")
    
    class Boxes(FloatLayout):
        def __init__(self, **kwargs):
            super(Boxes, self).__init__(**kwargs)
            bx1 = BoxLayout(orientation='horizontal')
            bx2 = BoxLayout(orientation='horizontal')
            bx3 = BoxLayout(orientation='horizontal')
            bx4 = BoxLayout(orientation='horizontal')
    
            for i in range(1,2):
                bx1.add_widget(Button(text=str(i)))
            for i in range(2,5):
                bx2.add_widget(Button(text=str(i)))
            for i in range(5,7):
                bx3.add_widget(Button(text=str(i)))
            for i in range(7,11):
                bx4.add_widget(Button(text=str(i)))
    
            self.boxes.add_widget(bx1)
            self.boxes.add_widget(bx2)
            self.boxes.add_widget(bx3)
            self.boxes.add_widget(bx4)
    
    
    class TestApp(App):
        def build(self):
            return Boxes()
    
    if __name__ == '__main__':
        TestApp().run()
    

