Trying to implement an application using ResponsiveView and having trouble both linking all the widgets and keeping all three view consistent. I began with a prototype using the backdrop view, which was fine for a mobile device, but fell short for a tablet or desktop. In the initial prototype I was able to identify the widget hierarchy of the status bar(s) and simply call them from a bound application level method. That is obviously not going to work in the ResponseView implementation, as each view may have different instances of the widgets. I expect that the best solution may be to create my own custom events, but verification or the suggestion of another better approach would be appreciated.
I would like to be able to update the right status bar to display properties about the selected items in list one. Since each of the three views may have its own instance of the status bar and lists, I need to update each for every event. Or figure out how to have a single widget for each item that can be used in each view. The implementation below will work for the tablet view, but not the mobile or desktop views. The mobile view is incomplete, as the full backdrop implementation is not present.
Below is a rather lengthy prototype that should display the problem(s):
from kivymd.app import MDApp
from kivymd.uix.list import MDList
from kivymd.uix.scrollview import ScrollView
from kivymd.uix.list import OneLineIconListItem
from kivymd.uix.boxlayout import MDBoxLayout
from kivymd.uix.screen import MDScreen
from kivymd.uix.responsivelayout import MDResponsiveLayout
from kivymd.uix.toolbar import MDTopAppBar
from kivy.properties import StringProperty, BooleanProperty, ObjectProperty
Version = '0.1'
MainAppKV = '''
#:import NoTransition kivy.uix.screenmanager.NoTransition
#:import Window kivy.core.window.Window
#:import IconLeftWidget kivymd.uix.list.IconLeftWidget
<NotificationBar>:
id: top_bar
title: "Title"
anchor_title: "center"
<LeftStatusBar>:
id: left_status_bar
IconLeftWidget:
id: status_icon
icon: ''
<RightStatusBar>:
id: right_status_bar
IconLeftWidget:
id: status_icon
icon: ''
<TableOneHeader>:
id: "table_one_header"
size_hint: [1, .12]
orientation: "horizontal"
Button:
id: "column_1"
text: "Column 1"
on_press: root.button_press(self)
Button:
id: "column_2"
text: "Column 2"
Button:
id: "column_3"
text: "Column 3"
<TableTwoHeader>:
id: "table_two_header"
size_hint: [1, .12]
orientation: "horizontal"
Button:
id: "column_1"
text: "Column 1"
Button:
id: "column_2"
text: "Column 2"
<ScrollViewOne>:
id: "scrollview_one"
MDSelectionList:
id: "mdselection_list"
spacing: "12dp"
on_selected: app.on_selected(*args)
on_unselected: app.on_unselected(*args)
OneLineIconListItem:
text: "List One, Item One"
OneLineIconListItem:
text: "List One, Item Two"
<ScrollViewTwo>:
id: "scrollview_two"
ListTwo:
id: "list_two"
OneLineIconListItem:
text: "List Two, Item One"
OneLineIconListItem:
text: "List Two, Item Two"
<ListOneLayout>:
id: "list_one_layout"
orientation: "vertical"
TableOneHeader:
ScrollViewOne:
<ListTwoLayout>:
id: "list_two_layout"
orientation: "vertical"
TableTwoHeader:
ScrollViewTwo:
<BackDropLayout>:
id: "backdrop_layout"
orientation: "vertical"
NotificationBar:
BoxLayout:
orientation: "horizontal"
size_hint: (1, .1)
LeftStatusBar:
size_hint: (.6, 1)
RightStatusBar:
size_hint: (.4, 1)
ListOneLayout:
<MyBackdropBackLayer@ScreenManager>
transition: NoTransition()
MDScreen:
ListOneLayout:
<SideBySideLayout>
orientation: "vertical"
NotificationBar:
BoxLayout:
orientation: "horizontal"
BoxLayout:
orientation: "vertical"
size_hint: (.5, 1)
LeftStatusBar:
ListTwoLayout:
BoxLayout:
orientation: "vertical"
size_hint: (.5, 1)
RightStatusBar:
ListOneLayout:
<MobileView>
id: "mobile_view"
name: "mobile"
MDScreen:
name: "backdrop"
BackDropLayout:
id: "mobile_layout"
<TabletView>
id: "tablet_view"
name: "tablet"
SideBySideLayout:
id: "tablet_layout"
<DesktopView>
id: "desktop_view"
name: "desktop"
SideBySideLayout:
id: "desktop_layout"
ResponsiveView:
'''
class ScrollViewOne(ScrollView):
pass
class TableOneHeader(MDBoxLayout):
pass
class TableTwoHeader(MDBoxLayout):
pass
class BackDropLayout(MDBoxLayout):
pass
class SideBySideLayout(MDBoxLayout):
pass
class MobileView(MDScreen):
pass
class TabletView(MDScreen):
pass
class DesktopView(MDScreen):
pass
class ResponsiveView(MDResponsiveLayout, MDScreen):
def __init__(self, **kw):
super().__init__(**kw)
self.mobile_view = MobileView()
self.tablet_view = TabletView()
self.desktop_view = DesktopView()
class LeftStatusBar(OneLineIconListItem):
status_text = StringProperty("Left-Status")
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.text = self.status_text
class RightStatusBar(OneLineIconListItem):
in_selection = BooleanProperty(False)
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.text = "None selected"
def update(self, item, remove=False):
if remove:
self.text = 'None selected'
return
self.text = "update selection"
class NotificationBar(MDTopAppBar):
pass
class ListOneLayout(MDBoxLayout):
pass
class ListTwoLayout(MDBoxLayout):
pass
class ScrollViewTwo(ScrollView):
pass
class ListTwo(MDList):
pass
class MainApp(MDApp):
status_left = ObjectProperty()
status_right = ObjectProperty()
def __init__(self):
super().__init__()
self.title = "Title (v{})".format(Version)
def build(self):
self.root = Builder.load_string(MainAppKV)
self.status_right = self.root.tablet_view.children[0].children[0].children[0].children[1]
self.status_left = self.root.tablet_view.children[0].children[0].children[1].children[1]
return self.root
def on_selected(self, instance_selection_list, instance_selection_item):
print("on_selected {}".format(instance_selection_item))
self.status_right.update(0)
def on_unselected(self, instance_selection_list, instance_selection_item):
print("on_unselected {}".format(instance_selection_item))
self.status_right.update(0, True)
if __name__ == "__main__":
MainApp().run()
