1
votes

This: (https://imgur.com/a/Y9Xwl) (can't format it for some reason) is the user interface I am currently trying to create in Kivy. I am having difficulty recreating this as I do not understand the layout system and I have read a lot of documentation, watched a lot of Youtube videos, tinkered with the code and still I cannot get the desired result. So far this is my code, it has all the widgets that I need within it, they're just not sized/positioned how I want them:

from kivy.app import App
from kivy.uix.label import Label
from kivy.lang import Builder
from kivy.properties import ListProperty
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.dropdown import DropDown
from kivy.uix.button import Button

from kivy.uix.screenmanager import ScreenManager, Screen, FadeTransition

class CaloriesScreen(Screen):
    pass

class categoriesScreen(Screen):
    pass

class loginScreen(Screen):
    pass

class registerScreen(Screen):
    pass

class shoppingListScreen(Screen):
    pass

class theScreenManager(ScreenManager):
    pass

root_widget = Builder.load_string('''
#:import FadeTransition kivy.uix.screenmanager.FadeTransition

theScreenManager:
    transition: FadeTransition()
    CaloriesScreen:

<CaloriesScreen>:
    name: 'calories'
    BoxLayout:
        orientation: 'vertical'

        BoxLayout:
            orientation: 'horizontal'
            size_hint: 1, .3
            Button:
                text: '<'
                size_hint: .1, 1
                font_size: 75
                background_normal: ""
                background_color: 0.18, .5, .92, 1
                on_release: app.root.current = 'main' 

            Label:
                text: 'Calories'
                halign: 'left'
                font_size: 50
                canvas.before:
                    Color:
                        rgb: 0.18, .5, .92
                    Rectangle:
                        pos: self.pos
                        size: self.size
            Widget:
                size_hint: .1, 1
                canvas.before:
                    Color:
                        rgb: 0.18, .5, .92
                    Rectangle:
                        pos: self.pos
                        size: self.size

        BoxLayout:
            orientation: 'horizontal'
            size_hint: 1, .4
            canvas.before:
                Color:
                    rgb: 0.8, 0.8, 0.8
                Rectangle:
                    pos: self.pos
                    size: self.size
            Label:
                text: 'Recipes'
                font_size: 30
                color: 0.18, .5, .92, 1
                size_hint: 1, 1


            Button:
                id: btn
                text: 'Select a recipe...'
                on_release: dropdown.open(self)
                height: '48dp'
                size_hint: .5, .3
                pos: self.x, .3

            DropDown:

                id: dropdown
                on_parent: self.dismiss()
                on_select: btn.text = '{}'.format(args[1])


                Button:
                    text: 'First recipe'
                    size_hint_y: None
                    height: '48dp'
                    on_release: dropdown.select('First Item')

                Button:
                    text: 'Second recipe'
                    size_hint_y: None
                    height: '48dp'
                    on_release: dropdown.select('Second Item')

                Button:
                    text: 'Third recipe'
                    size_hint_y: None
                    height: '48dp'
                    on_release: dropdown.select('Third Item')


            Button:
                text: '+'
                font_size: 30
                background_normal: ""
                background_color: 0.18, .5, .92, 1
                #on_release:

        BoxLayout:
            orientation: 'vertical'
            BoxLayout:
                orientation: 'horizontal'
                Label:
                    text: 'Food'
                    font_size: 30
                    color: 0.18, .5, .92, 1
                Label:
                    text: 'Cal'
                    font_size: 30
                    color: 0.18, .5, .92, 1
            BoxLayout:
                orientation: 'horizontal'
                Label:
                    text: 'Simple Cheese Omelette'
                    font_size: 30
                    color: 0.18, .5, .92, 1
                Label:
                    text: '241'
                    font_size: 30
                    color: 0.18, .5, .92, 1
            BoxLayout:
                orientation: 'horizontal'
                Label:
                    text: 'Burger'
                    font_size: 30
                    color: 0.18, .5, .92, 1
                Label:
                    text: '295'
                    font_size: 30
                    color: 0.18, .5, .92, 1
            BoxLayout:
                orientation: 'horizontal'
                Label:
                    text: 'Tomato and caper linguine '
                    font_size: 30
                    color: 0.18, .5, .92, 1
                Label:
                    text: '393'
                    font_size: 30
                    color: 0.18, .5, .92, 1
        BoxLayout:
            orientation: 'vertical'
            canvas.before:
                Color:
                    rgb: 0.8, 0.8, 0.8
                Rectangle:
                    pos: self.pos
                    size: self.size
            BoxLayout:
                orientation: 'horizontal'
                Label:
                    text: 'Total Cal'
                    font_size: 30
                    color: 0.18, .5, .92, 1
                Label:
                    text: '929'
                    font_size: 30
                    color: 0.18, .5, .92, 1
            BoxLayout:
                orientation: 'horizontal'
                Label:
                    text: 'You are under calories'
                    font_size: 30
                    color: 0.18, .5, .92, 1
            Button:
                text: 'Clear'
                font_size: 75
                background_normal: ""
                background_color: 0.18, .5, .92, 1
                #on_release:


''')

class RecipeApp(App):
    def build(self):
        return root_widget

if __name__ == "__main__":
    RecipeApp().run()

This(https://imgur.com/a/zW2z0) (can't format it for some reason) is what the output of that code looks like. The top bar with the "<" button is how I want it and I've only tried to edit the horizontal row of widgets below it. I cannot position the dropdown menu with the 'select your recipe' label how I would like it. I have tried altering it's y-axis multiple times but it always sinks to the botton of the boxlayout. I even tried giving it a new boxlayout just for the dropdown and tried doing: pos: self.parent.x, self.parent.y * 0.5 assuming it would go halfway up the y-axis of it's parent layout (the boxlayout) but still nothing. I am wondering whether it would be better to just use a floatlayout and manually position all the widgets but I am unsure how this will work well when I compile it into an APK for an Android device. What is the best way to go about positioning my widgets on the screen?

1

1 Answers

3
votes

Use pos_hint for this.
If pos_hint: {'top': 1}, the top of the widget will hit the roof of the parent box.
So if your widgets height is 30% of its parent box (size_hint: 0.5, 0.3), and you want it to be centered vertically, you want pos_hint: {'top': 0.5 + 0.3/2}, which means the top of the widget will be half way to the roof + half of the widgets height which is 15% of the parent box.
That takes us 65% to the top :)

size_hint: 0.5, 0.3
pos_hint: { 'top' : 0.65}

If the widgets size_hint is dynamic you can do something like this.

pos_hint: {'top': 0.5 + self.size_hint[1]/2}

And lets take your Select recipe button as an example:

Button:
    id: btn
    text: 'Select a recipe...'
    on_release: dropdown.open(self)
    height: '48dp'
    size_hint: .5, .3
    pos_hint: {'top': 0.5 + self.size_hint[1]/2}