'Weird effects of Kivy app on android/buildozer
So I was making a small app in Kivy and decided to try it on android for the first time when I noticed something was off. At first all my screens children of a ScreenManager had a y-offset up. I thought maybe I was getting confused with all the RelativeLayout positioning since Screens are RelativeLayouts but it didn't seemed like it. Below is an example. The red rectangle is the ScreenManager and the green one is the Screen itself. The button is on the very bottom of the screen, with pos_hint = {'center_x': .5, 'y':0}. I then realized I couldn't press the button on the right spot. I could only press it below it, the same amount as the y-offset of the screen, as if the button was rendered on a spot and its bounding box was on another spot. In this particular example I had a FloatLayout as root widget, with the ScreenManager and a footer (FloatLayout) as children.
On Windows, where I built the code, this wasn't a thing. The screen was positioned normally as I would expect, and I could click the button just fine. Then started to cut all complexity and made a small app to pinpoint the problem, but I wasn't able to. During this process I noticed that with just a simple screen with a button, my button sometimes takes the entire screen for itself, even with size_hints way smaller.
Again, this does not happen on Windows, only on android. I tested it with two different phones. At this moment this is my file structure:
And this is my code:
main.py
import os
import kivy.utils
from kivy.app import App
from kivy.lang.builder import Builder
from kivy.uix.floatlayout import FloatLayout
from kivy.core.window import Window
from kivy.uix.screenmanager import ScreenManager
from glob import glob
class FallGuysApp(App):
MAIN_LAYOUT_FILE = 'layout.kv'
def build(self):
root = self.load_kv_files()
return root
def load_kv_files(self):
main_path = os.path.dirname(os.path.realpath(__file__))
layout_files = glob(f"{main_path}/**/*.kv", recursive=True)
layout_files.remove(os.path.join(main_path, self.MAIN_LAYOUT_FILE))
for file in layout_files:
Builder.load_file(file)
return Builder.load_file(self.MAIN_LAYOUT_FILE)
class TopOfEverything(FloatLayout):
INITIAL_WINDOW_SIZE = [300, 533]
def __init__(self, **kwargs):
super(TopOfEverything, self).__init__(**kwargs)
self.decide_screen_size()
def decide_screen_size(self):
platform = kivy.utils.platform
if platform == 'win':
Window.size = self.INITIAL_WINDOW_SIZE
class MyScreenManager(ScreenManager):
def change_screen(self, screen_name, *args):
self.current = screen_name
if __name__ == '__main__':
FallGuysApp().run()
layout.kv
#: import LoginScreen screens.login_screen.LoginScreen
TopOfEverything:
BoxLayout:
orientation: 'vertical'
MyScreenManager:
canvas:
Color:
rgba: .5, .7, 0, .5
Rectangle:
pos: self.pos
size: self.size
Color:
rgba: 1, 0, 0, .8
Line:
rectangle: self.x, self.y, self.width, self.height
width: 5
LoginScreen:
login_screen.py
from kivy.uix.screenmanager import Screen
class LoginScreen(Screen):
pass
login_screen_layout.kv
<LoginScreen>:
name: "LoginScreen"
canvas:
Color:
rgba: 0, 1, 0, .8
Line:
rectangle: 0, 0, self.width, self.height
width: 4
LoginButton:
id: button
pos_hint: {'center_x': .5, 'y': 0}
Label:
text: "screen\n" + str(root.pos) + str(root.size) + "\nbutton\n" + str(button.pos) + str(button.size)
<LoginButton@Button>:
size_hint_min_y: 35
size_hint_x: .7
size_hint_y: .075
buildozer.spec (I took the liberty to exclude everything that was commented)
[app]
# (str) Title of your application
title = Fall Guys
# (str) Package name
package.name = fallguys
# (str) Package domain (needed for android/ios packaging)
package.domain = org.fallguys
# (str) Source code where the main.py live
source.dir = .
# (list) Source files to include (let empty to include all the files)
source.include_exts = py,png,jpg,kv,atlas
# (list) Source files to exclude (let empty to not exclude anything)
source.exclude_exts = spec, md
# (list) List of directory to exclude (let empty to not exclude anything)
source.exclude_dirs = bin, cache
# (str) Application versioning (method 1)
version = 0.3
# (list) Application requirements
# comma separated e.g. requirements = sqlite3,kivy
requirements = python3,kivy
# (str) Supported orientation (one of landscape, sensorLandscape, portrait or all)
orientation = portrait
#
# Android specific
#
# (bool) Indicate if the application should be fullscreen or not
#fullscreen = 0
# (list) Permissions
android.permissions = INTERNET
# (bool) If True, then skip trying to update the Android sdk
# This can be useful to avoid excess Internet downloads or save time
# when an update is due and you just want to test/build your package
android.skip_update = True
# (list) The Android archs to build for, choices: armeabi-v7a, arm64-v8a, x86, x86_64
# In past, was `android.arch` as we weren't supporting builds for multiple archs at the same time.
android.archs = arm64-v8a
# (bool) enables Android auto backup feature (Android API >=23)
android.allow_backup = True
[buildozer]
# (int) Log level (0 = error only, 1 = info, 2 = debug (with command output))
log_level = 2
# (int) Display warning if buildozer is run as root (0 = False, 1 = True)
warn_on_root = 1
Sometimes when I compile the same code again, it just works on android, but the same build when opened multiple times is always bugged (or not bugged at all), so I presume it is a build problem. I'm using Windows 10 with buildozer and WSL2, as recommended on the docs. Am I missing something? My build is broken? Is this a bug? Any thoughts are appreciated.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|





