I'm wanting to create a type of workflow using ScreenManager that progresses as options are selected. I have several screens defined within ScreenManager and within one screen I have created a Spinner with several options. I'm wanting to call a Function from the on_text and pass the selected Spinner value, perform a task based on the passed value and then move to the next screen in the workflow.
I've created a Function inside a class (Screen) with only a print() for testing purposes. When I select an option from the Spinner nothing happens.
I've only provided what I think is the relevant code...
kv file:
<HomeScreen>:
name: 'homeScreen'
BoxLayout:
orientation: 'horizontal'
Label:
id: 'home'
text: 'Home Screen'
<NewSession>:
name: 'newSession'
BoxLayout:
orientation: 'vertical'
Label:
id: new
text: 'Create New Session'
Spinner:
size_hint: None, None
size: 100, 25
id: category
font_size: 12
text: "Food Category" #default value showed
values: ["Beef","Pork","Poultry", "Fish"] #list of values to show
on_text: root.SelectCut(category.text)
Widget:
<CurrentSession>:
id: cs
name: 'currentSession'
BoxLayout:
orientation: 'vertical'
Label:
id: cSession
text: root.cSession
<History>:
name: 'history'
BoxLayout:
orientation: 'vertical'
Label:
id: 'history'
text: 'History Data Screen'
<ScreenManagement>:
HomeScreen:
NewSession:
CurrentSession:
History:
<AllScreen>:
orientation: 'vertical'
ScreenManagement:
id: sm
BoxLayout:
size_hint_y: None
height: 60
spacing: 5
padding: 5, 5, 0, 5
Button:
text: 'Home'
on_press: root.ids.sm.current = 'homeScreen'
Button:
text: 'New Session'
on_press: root.ids.sm.current = 'newSession'
Button:
text: 'Current Session'
on_press:
root.ids.sm.current = 'currentSession'
Button:
text: 'History'
on_press: root.ids.sm.current = 'history'
py file:
Builder.load_file("screenLayout.kv")
class ScreenManagement(ScreenManager):
pass
class HomeScreen(Screen):
pass
class NewSession(Screen):
def SelectCut(self, text):
print("In Select Cut")
print("Food Category: " + text)
self.sm.current = 'homeScreen'
class CurrentSession(Screen):
pass
class History(Screen):
pass
class AllScreen(BoxLayout):
pass
class WorkingTestApp(App):
def build(self):
self.root = AllScreen()
return self.root
if __name__ == '__main__':
WorkingTestApp().run()
I'm not able to figure out why nothing is happening when a selection is made from the Spinner and I'm not sure what the syntax will be from within the Function to move to the next screen.
Update:
Current code (minus imports)
kv:
<HomeScreen>:
name: 'homeScreen'
BoxLayout:
orientation: 'horizontal'
Label:
id: 'home'
text: 'Home Screen'
<NewSession>:
name: 'newSession'
BoxLayout:
orientation: 'vertical'
Label:
id: new
text: 'Create New Session'
Spinner:
size_hint: None, None
size: 100, 25
id: category
font_size: 12
text: "Food Category" #default value showed
values: ["Beef","Pork","Poultry", "Fish"] #list of values to show
on_text: root.SelectCategory()
Widget:
<SelectCut>:
name: 'selectCut'
BoxLayout:
orientation: 'vertical'
Label:
id: 'cut'
text: 'Select Cut Screen'
Widget:
<CurrentSession>:
name: 'currentSession'
BoxLayout:
orientation: 'vertical'
Label:
id: cSession
text: 'Current Session Screen'
<History>:
name: 'history'
BoxLayout:
orientation: 'vertical'
Label:
id: 'history'
text: 'History Data Screen'
<ScreenManagement>:
HomeScreen:
NewSession:
SelectCut:
CurrentSession:
History:
<AllScreen>:
orientation: 'vertical'
ScreenManagement:
id: sm
BoxLayout:
size_hint_y: None
height: 60
spacing: 5
padding: 5, 5, 0, 5
Button:
text: 'Home'
on_press: root.ids.sm.current = 'homeScreen'
Button:
text: 'New Session'
on_press: root.ids.sm.current = 'newSession'
Button:
text: 'Current Session'
on_press:
root.ids.sm.current = 'currentSession'
Button:
text: 'History'
on_press: root.ids.sm.current = 'history'
py:
Builder.load_file("screenLayout.kv")
class ScreenManagement(ScreenManager):
pass
class HomeScreen(Screen):
pass
class NewSession(Screen):
# This Function isn't executing consistently.
def SelectCategory(self):
print("Food Category: " + self.ids.category.text)
self.manager.current = 'selectCut'
class SelectCut(Screen):
pass
class CurrentSession(Screen):
pass
class History(Screen):
pass
class AllScreen(BoxLayout):
pass
class WorkingTestApp(App):
def build(self):
self.root = AllScreen()
return self.root
if __name__ == '__main__':
WorkingTestApp().run()
change your spinner's on_text: root.SelectCut(self, text) to on_text: root.SelectCut() the in your .py change def SelectCut(self, text): to def SelectCut(self): then to change the text you can use self.ids.category.text to read or alter the spinner's text and add root.ids.sm.current = 'your screen' to this function as well
Related
MDScreen:
MDNavigationLayout:
ScreenManager:
MDScreen:
MDBoxLayout:
orientation:'vertical'
MDToolbar:
title:"Teacher Section"
left_action_items:[["menu",lambda x:nav_drawer.set_state("open")]]
right_action_items:[["magnify",lambda x:None]]
elevation:5
MDScreen:
ScreenManager:
id:nestedsm
MDScreen:
name:"Screen1"
MDLabel:
text:"Screen1"
MDScreen:
name:"Screen2"
MDLabel:
text:"Screen2"
Widget:
MDNavigationDrawer:
id: nav_drawer
ContentNavigationDrawer:
orientation: 'vertical'
padding: "8dp"
spacing: "8dp"
Image:
id: avatar
size_hint: (1,1)
source: "images/kitten.png"
MDLabel:
text: "Bhushan Ghevde"
font_style: "Subtitle1"
size_hint_y: None
height: self.texture_size[1]
MDLabel:
text: "bhushanghevde15#gmail.com"
size_hint_y: None
font_style: "Caption"
height: self.texture_size[1]
ScrollView:
DrawerList:
id: md_list
MDList:
OneLineIconListItem:
text: "Add Teacher"
on_release:
nestedsm.current = 'Screen1'
IconLeftWidget:
icon: "face-profile"
OneLineIconListItem:
text: "Upload"
on_release:
nestedsm.current = 'Screen2'
IconLeftWidget:
icon: "upload"
I am creating a collage level app for manageing student details . The Normal Screenmanager works perfectly fine . while i was trying nested Screen manager i am facing problems . the problem is , when i try to change screen from navigation drawer , it changes screen but doesnt hide automatically , i have to click back again to hide. any help is appreciated . Thank you in advanced..
i have provided video of issue
Welcome, you can add the line:
root.ids.nav_drawer.set_state(new_state='toggle', animation=True)
Under the "on_release" of every list item, if you are adding those using the "for loop", you should add them like:
self.root.ids.content_drawer.ids.md_list.add_widget(OneLineIconListItem(icon=icon_name, text="Item number 1", on_release=lamda x:(self.root.ids.nav_drawer.set_state(new_state='toggle', animation=True))))
Or you can just implement it inside of the kivy lang:
Screen:
#MDNavigationLayout: #unknown class
ScreenManager:
Screen:
MDBoxLayout:
orientation:'vertical'
MDToolbar:
title:"Teacher Section"
left_action_items:[["menu",lambda x:nav_drawer.set_state("open")]]
right_action_items:[["magnify",lambda x:None]]
elevation:5
MDScreen:
ScreenManager:
id:nestedsm
MDScreen:
name:"Screen1"
MDLabel:
text:"Screen1"
MDScreen:
name:"Screen2"
MDLabel:
text:"Screen2 jbsidis"
Widget:
MDNavigationDrawer:
id: nav_drawer
BoxLayout:
orientation: 'vertical'
padding: "8dp"
spacing: "8dp"
Image:
id: avatar
size_hint: (1,1)
source: "images/pro.jpg" #"images/kitten.png"
MDLabel:
text: "Bhushan Ghevde"
font_style: "Subtitle1"
size_hint_y: None
height: self.texture_size[1]
MDLabel:
text: "bhushanghevde15#gmail.com"
size_hint_y: None
font_style: "Caption"
height: self.texture_size[1]
ScrollView:
MDList:
id: md_list
OneLineIconListItem:
text: "Add Teacher"
on_release:
nestedsm.current = 'Screen1'
root.ids.nav_drawer.set_state(new_state='toggle', animation=True)
IconLeftWidget:
icon: "face-profile"
OneLineIconListItem:
text: "Upload"
on_release:
nestedsm.current = 'Screen2'
root.ids.nav_drawer.set_state(new_state='toggle', animation=True)
IconLeftWidget:
icon: "upload"
Picture:
I am trying build an app in Python using Kivymd and i just started learning this kivymd framework so the problem i am facing is when i am trying to change screen from LoginScreen to HomeScreen, it raises error. I am unable to understand what's wrong in my code.
I wanted it to change screen to HomeScreen and then show the list on pressing button 'Join Chat'.
Here is the code:
main.py
from kivymd.app import MDApp
from kivy.lang import Builder
from kivy.uix.screenmanager import Screen,ScreenManager
from kivymd.uix.list import MDList, OneLineIconListItem,IconLeftWidget
class LoginScreen(Screen):
pass
class HomeScreen(Screen):
pass
class DemoApp(MDApp):
def build(self):
self.theme_cls.theme_style="Dark"
self.sm=ScreenManager()
self.sm.add_widget(LoginScreen(name="login"))
self.sm.add_widget(HomeScreen(name="home"))
screen=Builder.load_file("helper_file.kv")
return screen
def do_login(self):
self.sm.current = "home"
for i in range(20):
st_name="student "
list_item = OneLineIconListItem(text=f"student {str(i)}")
list_item.add_widget(IconLeftWidget(icon= "alpha-a-box"))
self.root.ids.users_lst.add_widget(list_item)
DemoApp().run()
helper_file.kv
ScreenManager:
LoginScreen:
HomeScreen:
<LoginScreen>:
name: "login"
Screen:
MDLabel:
text: "Demo App"
halign: "center"
pos_hint: {"center_x": .5, "center_y": .8}
theme_text_color: "Primary"
MDTextField:
hint_text: "Enter username"
helper_text: "to join the chat (test mode)"
helper_text_mode: "on_focus"
icon_right: "android"
icon_right_color: app.theme_cls.primary_color
pos_hint:{'center_x': 0.5, 'center_y': 0.5}
size_hint_x:None
width:311
MDRoundFlatButton:
text: "Join Chat"
pos_hint: {"center_x": .5, "center_y": .4}
on_release: app.do_login()
MDLabel:
text: "This is testing mode only"
halign: "center"
pos_hint: {"center_x": .5, "center_y": .2}
theme_text_color:"Hint"
<HomeScreen>:
name: "home"
Screen:
BoxLayout:
orientation: "vertical"
MDToolbar:
title: "Demo Chat Application"
ScrollView:
MDList:
id: users_lst
On running this, the login screen working well but on pressing the button 'Join Chat' it raises the following error:
self.root.ids.users_lst.add_widget(list_item)
File "kivy\properties.pyx", line 864, in kivy.properties.ObservableDict.__getattr__
AttributeError: 'super' object has no attribute '__getattr__'
| 1 |
class HomeScreen(Screen):
pass
<HomeScreen>:
name: "home"
Screen:
BoxLayout:
orientation: "vertical"
MDToolbar:
title: "Demo Chat Application"
ScrollView:
MDList:
id: users_lst
You have a screen which has a screen, that's not what you want to do.
<HomeScreen>:
name: "home"
BoxLayout:
orientation: "vertical"
MDToolbar:
title: "Demo Chat Application"
ScrollView:
MDList:
id: users_lst
#######################################################
#######################################################
| 2 |
Parent doesn't have access of the id of inner children children's. (Not clear I know, So I'm gonna give you a lot of print to help you understand).
def do_login(self):
self.root.current = "home"
for i in range(20):
st_name = "student "
list_item = OneLineIconListItem(text=f"student {str(i)}")
list_item.add_widget(IconLeftWidget(icon="alpha-a-box"))
print("this is my App:", self)
print("this is my ScreenManager:", self.sm)
print("this is my global app visual widget (which is equal to ScreenManager here):", self.root)
print("this is the ScreenManager's dictionnary containing the widgets referenced with their id:", self.root.ids)
print("this is the current Screen:",self.root.current_screen)
print("this is current Screen dictionnary containing the widgets referenced with their id:", self.root.current_screen.ids)
print("this is the actual MDList", self.root.current_screen.ids["users_lst"])
self.root.current_screen.ids["users_lst"].add_widget(list_item)
I'm trying to make the button click on_release: app.proximo () have the action to go to the next card MDFloatLayout, but I'm not getting it, could someone help me how could it work?
Below the main.py file, where to start the app, main.kv file, where is the main app and finally the dashboard.kv file where I am calling my card inside the app
from kivymd.app import MDApp
from kivy.lang import Builder
from kivy.uix.screenmanager import Screen
class DashBoard(Screen):
pass
class FirstScreen(Screen):
pass
class Lavanderia(MDApp):
def build(self):
self.title="Texto Titulo"
self.theme_cls.primary_palette = "LightBlue"
return Builder.load_file("main.kv")
def proximo(self):
self.root.ids.carousel.load_next(mode="proximo")# Próximo Card
def fecharApp(self):
self.stop()# Fecha Aplicativo
Lavanderia().run()
#:import rgba kivy.utils.get_color_from_hex
#: include dashboard.kv
#: include firstscreen.kv
NavigationLayout:
id: nav_layout
ScreenManager:
Screen:
BoxLayout:
orientation:'vertical'
MDToolbar:
title: app.title
elevation:10
left_action_items:[["menu", lambda x: nav_drawer.set_state()]]
ScreenManager:
id: screen_manager
DashBoard:
id:dashboard
name:"dashboard"
FirstScreen:
id:first_screen
name:"first_screen"
MDNavigationDrawer:
id: nav_drawer
BoxLayout:
orientation:'vertical'
padding:"8dp"
spacing:"8dp"
Image:
pos_hint:{"x":.24,"y":.0}
size_hint: None, None
size:dp(146), dp(158)
source:"images/logo.png"
ScrollView:
MDList:
OneLineIconListItem:
text:"Tela 1"
on_release:
screen_manager.current = "dashboard"
nav_drawer.set_state()
IconLeftWidget:
icon:"dishwasher"
OneLineIconListItem:
text:"Tela 2"
on_release:
screen_manager.current = "first_screen"
nav_drawer.set_state()
IconLeftWidget:
icon:"dishwasher"
<DashBoard>:
MDFloatLayout:
MDCard:
size_hint: dp(.45), dp(.8)
pos_hint:{"center_x": .5, "center_y": .5}
Carousel:
id:carousel
MDFloatLayout:
MDTextField:
hint_text:"Texto 1"
size_hint_x:dp(.8)
pos_hint:{"center_x": .5, "center_y": .48}
MDRaisedButton:
text: "Proximo"
size_hint_x:dp(.8)
pos_hint:{"center_x":.5,"center_y":.2}
on_release: app.proximo() # Proximo step
MDFloatLayout:
MDLabel:
text:"Texto Final Conclusão"
theme_text_color:"Custom"
bold:True
pos_hint:{"center_x":.68,"center_y":.5}
font_style:"H5"
MDRaisedButton:
text: "Fechar Aplicativo"
text_color:rgba("#00FF69")
size_hint_x:dp(.8)
pos_hint:{"center_x":.5,"center_y":.4}
md_bg_color:rgba("#333333")
on_release: app.fecharApp() #fechar Aplicativo
You are trying to ger the carrousel through the root screen, but it is inside the dashboard screen.
So you will have to navigate there first, and only then you can call your function.
def proximo(self):
dashboard = self.root.ids.dashboard
carousel = dashboard.ids.carousel
carousel.load_next(mode="proximo")
# Same as
# self.root.ids.dashboard.ids.carousel.load_next(mode="proximo")
I am new to Kivy, so I have a question that I want to develop two screen in Kivy, the first one is about entering user details and passwords (no authentication, at this moment) and then second screen displays the user name (entered at the previous screen) and displays user name along with other widgets.
The basic idea is to get the value of a user form userlogin screen and display it to another screen.
Here is my code,
from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.properties import StringProperty # #UnresolvedImport
class LoginScreen(Screen):
text = StringProperty()
def change_text(self):
self.text = ''
self.manager.current = 'StocksGUIScreen'
class StocksGUIScreen(Screen):
label_text = StringProperty('')
#pass
class PortfolioUIApp(App):
#user_name = StringProperty()
pass
PortfolioUIApp().run()
Here is my .kv file:
ScreenManager:
id: screen_manager
LoginScreen:
id: login_screen
name: 'LoginScreen'
manager: screen_manager
StocksGUIScreen:
id: stocks_gui
name: 'StocksGUIScreen'
manager: screen_manager
label_text: login_screen.text
<LoginScreen>:
BoxLayout:
orientation: 'vertical'
BoxLayout:
Label:
text: "User Name"
size_hint: 0.3,0.2
#pos: root.x, root.top-self.height
color: 0,1,0,1
TextInput:
id: user_name
size_hint: 0.3,0.2
#on_text: root.user_name
BoxLayout:
Label:
text: "Password"
size_hint: 0.3,0.2
TextInput:
id: pass_word
password: True
size_hint: 0.3,0.2
BoxLayout:
Button:
text: 'Log In'
size_hint: 0.3,0.2
on_press:
#root.manager.current = 'StocksGUIScreen'
root.label_text: user_name
root.change_text()
Button:
text: 'Cancel'
size_hint: 0.3,0.2
on_release: app.stop()
<StocksGUIScreen>:
BoxLayout:
orientation: 'vertical'
BoxLayout:
orientation: 'horizontal'
TextInput:
size_hint_x: 50
id: ticker_search
Button:
text: "Go"
size_hint_x: 25
on_press: root.search_stock()
id: search_box
Label:
text: root.label_text
size_hint_x: 25
BoxLayout:
height: "10dp"
size_hint_y: 5
Label:
size_hint_x: .2
size_hint_y: .1
text: "Advice"
color: [1,0,0,1]
text_size: self.size
halign: 'left'
valign: 'top'
ScrollView:
size: self.size
GridLayout:
id: layout_content
size_hint_y: None
cols: 1
row_default_height: '20dp'
row_force_default: True
spacing: 0, 0
padding: 0, 0
color: [1,0,0,1]
Label:
text: "Lorem ipsum dolor sit amet"*10
id: advice_message
text_size: self.size
halign: 'left'
valign: 'top'
BoxLayout:
height: "10dp"
size_hint_y: 10
Label:
size_hint_x: .2
size_hint_y: .1
text: "Graphical Stuff"
id: graphical_stuff
text_size: self.size
halign: 'left'
valign: 'top'
AsyncImage:
source: "abc.png"
id: graphical_stuff
allow_stretch: True
keep_ratio: False
pos: 200,300
size: root.width*0.5,root.height*0.2
BoxLayout:
orientation: 'horizontal'
Button:
text: 'My settings button'
Button:
text: 'Back to Log in screen'
on_press: root.manager.current = 'LoginScreen'
What is wrong in this code, any help/guidance would be highly appreciated plz
If you want this setup, you can set an attribute on the first screen. Access it by id in your second screen.
from kivy.app import App
from kivy.uix.screenmanager import Screen
from kivy.lang import Builder
from kivy.properties import StringProperty
class Screen1(Screen):
username = StringProperty("")
class Screen2(Screen):
username = StringProperty("")
root = Builder.load_string('''
<Screen1>:
BoxLayout:
orientation: "vertical"
TextInput:
id: username
Button:
text: "Login"
on_release: root.username = username.text; root.manager.current = "screen2"
<Screen2>:
name: "screen2"
Label:
text: root.username
ScreenManager:
Screen1:
id: loginscreen
Screen2:
username: loginscreen.username
''')
class MyApp(App):
def build(self):
return root
I am trying to create screen with some menu toggle buttons and then a nested screen manager that I can switch screen manager only inside the container and leave the menu outside of the container intact. When I used a combination of Boxlayouts and Gridlayouts everything gets in top of each other.
from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.gridlayout import GridLayout
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.label import Label
from kivy.graphics.context_instructions import Color
from kivy.uix.screenmanager import Screen, ScreenManager
class ScreenManagement(FloatLayout):
pass
class IomApp(App):
def build(self):
return ScreenManagement()
if __name__ == '__main__':
IomApp().run()
Kivy file:
<LabelCases#Label>:
height: '40dp'
font_size: 18
<TextInputCases#TextInput>:
height: '40dp'
size_hint_y: None
font_size: 18
write_tab: False
multiline: False
on_text_validate: root.foo()
<ScreenManagement>:
BoxLayout:
orientation: "vertical"
BoxLayout:
height: "80dp"
size_hint_y: None
Label:
text: 'Patient info Label'
BoxLayout:
orientation: 'horizontal'
BoxLayout:
orientation: 'vertical'
size_hint_x: 20
ToggleButton:
text: 'Case Info'
group: 'g1'
on_screen:
ToggleButton:
text: 'Modalities'
group: 'g1'
ToggleButton:
text: 'Report Editing'
group: 'g1'
ToggleButton:
text: 'Printing/Exporting'
group: 'g1'
ToggleButton:
text: 'Settings'
group: 'g1'
BoxLayout:
orientation: 'vertical'
size_hint_x: 80
ScreenManager:
id: "Screen1"
Screen:
name: "Case_info_screen"
BoxLayout:
orientation: 'vertical'
spacing: 20
orientation: 'vertical'
size_hint: (.5, .5)
pos_hint: {'center_x':.5, 'center_y':.5}
Label:
text: "Case Info"
size_hint_y: 25
GridLayout:
cols: 2
padding: 50
spacing: 15
size_hint_y: 50
LabelCases:
text: 'First Name: '
TextInputCases:
LabelCases:
text: 'Last Name: '
TextInputCases:
LabelCases:
text: 'MRN: '
TextInputCases:
LabelCases:
text: 'Date of Birth: '
TextInputCases:
LabelCases:
text: 'Hospital: '
TextInputCases:
LabelCases:
text: 'Diagnosis: '
TextInputCases:
Label:
text: "Surgical and Techical Staff"
size_hint_y: 25
BoxLayout:
Button:
height: "40dp"
size_hint_y: None
text: "Back"
Button:
height: "40dp"
size_hint_y: None
text: "Next"
You've used a layout, yet even if you made the layout's size relative the sizes of its children were fixed/static (height: '40dp'). If you remove size_hint_y: None from TextInputCases, you'll see what's hapenning.
You kv code
<LabelCases#Label>:
font_size: 18
<TextInputCases#TextInput>:
font_size: 18
write_tab: False
multiline: False
on_text_validate: root.foo()
<ScreenManagement>:
BoxLayout:
orientation: "vertical"
BoxLayout:
height: "80dp"
size_hint_y: None
Label:
text: 'Patient info Label'
BoxLayout:
orientation: 'horizontal'
BoxLayout:
orientation: 'vertical'
size_hint_x: .20
ToggleButton:
text: 'Case Info'
group: 'g1'
on_screen:
ToggleButton:
text: 'Modalities'
group: 'g1'
ToggleButton:
text: 'Report Editing'
group: 'g1'
ToggleButton:
text: 'Printing/Exporting'
group: 'g1'
ToggleButton:
text: 'Settings'
group: 'g1'
BoxLayout:
orientation: 'vertical'
size_hint_x: .80
ScreenManager:
id: "Screen1"
Screen:
name: "Case_info_screen"
BoxLayout:
orientation: 'vertical'
spacing: 20
orientation: 'vertical'
size_hint: (.5, .8)
pos_hint: {'center_x':.5, 'center_y':.5}
Label:
text: "Case Info"
size_hint_y: .25
GridLayout:
cols: 2
padding: 50
spacing: 15
size_hint_y: .70
LabelCases:
text: 'First Name: '
TextInputCases:
LabelCases:
text: 'Last Name: '
TextInputCases:
LabelCases:
text: 'MRN: '
TextInputCases:
LabelCases:
text: 'Date of Birth: '
TextInputCases:
LabelCases:
text: 'Hospital: '
TextInputCases:
LabelCases:
text: 'Diagnosis: '
TextInputCases:
Label:
text: "Surgical and Techical Staff"
BoxLayout:
height: "40dp"
size_hint_y: None
Button:
text: "Back"
Button:
text: "Next"
But I'd rather recommend to make something like ScrollView -> GridLayout -> all children, so that you can have content with a fixed size (with an ability to scroll) and preserve the "iframe"-like layout. ^^