Recycle view inside not Showing in box layout - Kivy - python-3.x

I have this code below - working on some kind of online streaming app.
My aim is to make the recycler view item occupy 90% while my top navigation takes 10%.
what I have done is put both in a box layout but the recycler view item seem to dissappear. I dont get errors but just a blank screen in the place where the recycler view item is supposed to show.
what Im I doing wrong
Thank you for your help
py
import os
from kivymd.app import MDApp
from kivy.uix.boxlayout import BoxLayout
from kivymd.uix.list import OneLineListItem, OneLineRightIconListItem, OneLineAvatarIconListItem, OneLineAvatarListItem, IRightBodyTouch
from kivymd.uix.gridlayout import MDGridLayout
from kivymd.uix.button import MDFlatButton, MDRectangleFlatButton, MDRaisedButton
from kivymd.uix.boxlayout import MDBoxLayout
from kivy.uix.recycleview import RecycleView
from kivy.uix.popup import Popup
from kivy.uix.screenmanager import ScreenManager, Screen
from kivymd.uix.screen import MDScreen
from kivy.properties import StringProperty
from pathlib import Path, PurePath
# Music Path
storageLocation = Path.cwd()
if Path('Books').is_dir():
storageLocation = Path.cwd() / 'Books'
# Check if file is in SD card
# elif Path.is_mount():
else:
storageLocation = Path.cwd() / 'Books'
storageLocation.mkdir()
class RecycleViewRow(BoxLayout):
text = StringProperty()
class MainScreen(MDScreen):
def __init__(self, **kwargs):
super(MainScreen, self).__init__(**kwargs)
booksdir = [f for f in storageLocation.iterdir() if f.is_dir()]
self.children[0].data = [{'text': str(x), 'id': str(x)} for x in booksdir]
self.theFiles = [self.children[0].data]
return
class Playlist(MDScreen):
def on_enter(self, *args):
return
class Main(MDApp):
def build(self):
self.theme_cls.theme_style = "Dark"
sm = ScreenManager()
sm.add_widget(MainScreen(name='MainScreen'))
sm.add_widget(Playlist(name='Playlist'))
sm.add_widget(Test(name="Test"))
return sm
def fill_playlist(self, dir):
self.root.current = 'Playlist' # this also clears the play list
playlist = self.root.get_screen('Playlist')
for sub in os.listdir(dir):
playlist.ids.Box.add_widget(OneLineAvatarIconListItem(text=sub))
Kivy
<RecycleViewRow>:
orientation: 'vertical'
OneLineAvatarIconListItem:
text: root.text
#on_press: app.root.message_box(root.text)
#on_release:app.root.current = 'Playlist'
on_release: app.fill_playlist(root.text)
Container:
id: container
MDIconButton:
icon: "download"
<MainScreen>:
MDBoxLayout
orientation:'horizontal'
MDToolbar:
title: 'Books'
left_action_items: [['menu', lambda x: x]]
right_action_items: [['dots-vertical', lambda x: x]]
MDBoxLayout
RecycleView:
id: rv
viewclass: 'RecycleViewRow'
spacing: 40
padding:10, 10
RecycleBoxLayout:
default_size: None, dp(56)
default_size_hint: 1, None
size_hint_y: None
height: self.minimum_height
orientation: 'vertical'
<Playlist>
MDBoxLayout:
orientation:'vertical'
spacing: 5
size_hint_y: None
height: self.minimum_height
MDList:
id:Box

The main issue with your code is the line:
self.children[0].data = [{'text': str(x), 'id': str(x)} for x in booksdir]
because self.children[0] in the MainScreen class is the MDBoxLayout. You should set the data for the RecycleView class, which has an id of rv. So that line should be:
self.ids.rv.data = [{'text': str(x), 'id': str(x)} for x in booksdir]
However, that won't work inside the __init__() method of MainScreen, bcause the ids have not yet been assigned at that point. Here is an approach that handles both those issues:
class MainScreen(MDScreen):
def __init__(self, **kwargs):
super(MainScreen, self).__init__(**kwargs)
Clock.schedule_once(self.build_rv)
def build_rv(self, dt):
booksdir = [f for f in storageLocation.iterdir() if f.is_dir()]
self.ids.rv.data = [{'text': str(x), 'id': str(x)} for x in booksdir]
self.theFiles = [self.ids.rv.data]
By delaying the execution of build_rv() with Clock.schedule_once(), the ids are available.

Related

A non-existent line

I'm learning Kivy and I'm on the MDExpansionPanel widget.
Data source from a JSON I use the keys to assemble my panels and the values to compose my Contents.
It happens that I'm able to do it but an extra line always appears in my contents.
I would like your help to delete this line.
I will post my code below:
from kivy.lang import Builder
from kivymd.app import MDApp
from kivymd.uix.boxlayout import MDBoxLayout
from kivymd.uix.expansionpanel import MDExpansionPanel, MDExpansionPanelOneLine
from kivy.properties import StringProperty, ObjectProperty
json_data = {'01001BA476': {'price': '74.73',
'product_code': '000003',
'quantity': '100'},
'0100251633': {'price': '92.07',
'product_code': '000156',
'quantity': '1000'}}
KV = '''
<ClassDetails>
orientation: 'vertical'
adaptive_height: True
OneLineIconListItem:
id: info_line
text: root.text
on_press: root.action()
IconLeftWidget:
icon: 'star'
on_press: print(f'star pressed on line: {info_line.text}')
ScrollView:
MDGridLayout:
id: box
cols: 1
adaptive_height: True
'''
class ClassDetails(MDBoxLayout):
text = StringProperty()
action = ObjectProperty()
class InvoicePanel(MDExpansionPanel):
pass
class Test(MDApp):
def build(self):
return Builder.load_string(KV)
def fechar_pedido(self):
print('You clicked on the information line')
def on_start(self):
for class_title, class_details in json_data.items():
cd = ClassDetails()
expansion_panel = InvoicePanel(panel_cls=MDExpansionPanelOneLine(text=f'Invoice #: {class_title}'), content=cd)
self.root.ids.box.add_widget(expansion_panel)
for item in class_details.items():
cd.add_widget(ClassDetails(
text=str(class_details.values()), action=self.fechar_pedido))
Test().run()
I think the extra line is coming from setting your initial content to a ClassDetails instance, which has a OneLineIconListItem in its definition. Try replacing the content with a simple MDBoxLayout instead:
def on_start(self):
for class_title, class_details in json_data.items():
print(class_title, class_details)
# cd = ClassDetails()
cd = MDBoxLayout(orientation='vertical', adaptive_height=True)
expansion_panel = InvoicePanel(panel_cls=MDExpansionPanelOneLine(text=f'Invoice #: {class_title}'), content=cd)
self.root.ids.box.add_widget(expansion_panel)
for item in class_details.items():
print('\titem:', item)
cd.add_widget(ClassDetails(
text=str(class_details.values()), action=self.fechar_pedido))

Change TextInput to display only function for Kivy Python

I'm still new to kivy and still relatively new to Python.
I have main. py. I plan to have WindowGUI take a number of inputs from main.py and display them in its textbox.
Here is what I have:
from os import curdir
from posixpath import dirname
import kivy
from kivy.app import App
from kivy.uix.label import Label
from kivy.uix.gridlayout import GridLayout # one of many layout structures
from kivy.uix.textinput import TextInput # allow for ...text input.
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.button import Button
from kivy.uix.widget import Widget
from kivy.core.window import Window
from kivy.uix.spinner import Spinner
from kivy.uix.dropdown import DropDown
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.lang import Builder
from kivy.properties import ObjectProperty
kivy.require('2.0.0')
class MainGUI(Screen):
encoder = ObjectProperty()
mileage = ObjectProperty()
voltage = ObjectProperty()
power = ObjectProperty()
camera = ObjectProperty()
engaged = ObjectProperty()
idle = ObjectProperty()
log = ObjectProperty()
clear = ObjectProperty()
status = ObjectProperty(None)
def __init__(self, saySomething):
super().__init__() #Go up to __init__ of App
self.saySomething = saySomething
def power_option(self):
self.power.text = "Power"
def print_status(self):
self.ids.Status_screen.text = self.saySomething
return self.ids.Status_screen.text
class CameraGUI(Screen):
def __init__(self, **kwargs): #kwargs is just a variable. it could be "banana" or "apple"
super().__init__() #Go up to __init__ of App
class GUIManager(ScreenManager):
pass
kv = Builder.load_file('newWindow.kv')
class WindowGUI(App):
def __init__(self):
super().__init__()
# self.say = say
print("TRY ME!!!!")
def build(self):
self.title = 'IamHero'
return kv
if __name__ == '__main__':
myWindowGUI = WindowGUI()
myMainGUI = MainGUI('I am hero!')
myWindowGUI.run()
###########################_newWindow.kv_#############################
GUIManager:
MainGUI:
CameraGUI:
<MainGUI>:
name: "main"
status: Status_screen
GridLayout:
cols: 2
size: root.width, root.height #covers entire window
padding: 15
GridLayout:
cols:1
spacing: 10
GridLayout:
cols:2
size_hint: .25,.1
Label:
id: Engaged
text: "Engaged"
Label:
id: Idle
text: "Idle"
TextInput:
# size_hint: 1
id: Status_screen
multiline: True
readonly: True
background_color: .6, .7, 0, 1
text: root.print_status()
#on_text: root.print_status()
GridLayout:
cols:2
size_hint: .25,.1
Button:
id: Log
text: "Log status"
# size_hint_x: .5
Button:
id: Clear
text: "Clear"
However, I got the following error:
Traceback (most recent call last):
File "c:/Users/Jojo/#RaspberryPi4/Test/WindowGUI.py", line 57, in <module>
kv = Builder.load_file('newWindow.kv')
File "C:\Users\Jojo\Anaconda3\lib\site-packages\kivy\lang\builder.py", line 306, in load_file
return self.load_string(data, **kwargs)
File "C:\Users\Jojo\Anaconda3\lib\site-packages\kivy\lang\builder.py", line 408, in load_string
self._apply_rule(
File "C:\Users\Jojo\Anaconda3\lib\site-packages\kivy\lang\builder.py", line 659, in _apply_rule
child = cls(__no_builder=True)
TypeError: __init__() got an unexpected keyword argument '__no_builder'
Any ideas about what I did wrong?
You cannot require a positional argument in the __init__() of a class that you intend to use in kv. Your __init__() for MainGUI:
def __init__(self, saySomething):
requires an argument for saySomething. An easy way around that is to just make saySomething into a StringProperty of MainGUI. Then you don't even need to implement an __init__():
class MainGUI(Screen):
encoder = ObjectProperty()
mileage = ObjectProperty()
voltage = ObjectProperty()
power = ObjectProperty()
camera = ObjectProperty()
engaged = ObjectProperty()
idle = ObjectProperty()
log = ObjectProperty()
clear = ObjectProperty()
status = ObjectProperty(None)
saySomething = StringProperty('Hi')
# def __init__(self, saySomething):
# super().__init__() #Go up to __init__ of App
# self.saySomething = saySomething
Then you can set the value of saySomething just like any other property in the kv:
<MainGUI>:
name: "main"
status: Status_screen
saySomething: 'I am hero!'
or in python you can do:
MainGUI(saySomething='I am hero!')
Also, the line:
myMainGUI = MainGUI('I am hero!')
(which will no longer work) is creating an instance of MainGUI that is unused. So that line of code can be deleted.

add recycle view item to another screen from a recycle view- kivy

I have two screens. MainScreen and Playlist. MainScreen has a RecycleView method added that displays list of items. These items are created from folder names(directories). I want the files inside each folder(directories) to open on the Playlist Screen depending on which directory name is clicked.
I intend to clear the screen immediately after the user leaves the screen.
from kivymd.app import MDApp
from kivymd.uix.button import MDFlatButton, MDRectangleFlatButton
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.recycleview import RecycleView
from kivy.uix.screenmanager import ScreenManager, Screen
from kivymd.uix.screen import MDScreen
from pathlib import Path, PurePath
# Music Path
storageLocation = Path.cwd()
if Path('Books').is_dir():
storageLocation = Path.cwd() / 'Books'
class RecycleViewRow(BoxLayout):
text = StringProperty()
class MainScreen(MDScreen):
def __init__(self, **kwargs):
super(MainScreen, self).__init__(**kwargs)
booksdir = [f for f in storageLocation.iterdir() if f.is_dir()]
self.children[0].data = [{'text': str(x), 'id': str(x)} for x in booksdir]
# print(self.children[0].data)
class Playlist(MDScreen):
def on_pre_enter(self, *args):
self.ids.Box.clear_widgets()
#self.ids.Box.add_widget(MDRectangleFlatButton(text="done", ))
print(self.manager.ids)
return
class Main(MDApp):
def build(self):
sm = ScreenManager()
sm.add_widget(MainScreen(name='MainScreen'))
sm.add_widget(Playlist(name='Playlist'))
sm.add_widget(Test(name="Test"))
return sm
Main().run()
.kv
<RecycleViewRow>:
orientation: 'vertical'
Button:
text: root.text
#on_press: app.root.message_box(root.text)
on_release:app.root.current = 'Playlist'
<MainScreen>:
RecycleView:
id: rv
viewclass: 'RecycleViewRow'
RecycleBoxLayout:
default_size: None, dp(56)
default_size_hint: 1, None
size_hint_y: None
height: self.minimum_height
orientation: 'vertical'
<Playlist>
BoxLayout:
orientation: 'vertical'
id:Box
You can trigger a method from your RecycleViewRow, like this:
<RecycleViewRow>:
orientation: 'vertical'
Button:
text: root.text
on_release: app.fill_playlist(root.text)
Then, the the fill_playlist() method. you can fill the PlayList:
def fill_playlist(self, dir):
self.root.current = 'Playlist' # this also clears the play list
playlist = self.root.get_screen('Playlist')
for sub in os.listdir(dir):
playlist.ids.Box.add_widget(MDRectangleFlatButton(text=sub))

Kivy RecycleView SelectableButton Does not switch to a Dynamic Layout Page

Am working on a Project that has a RecycleView that contains details of patients.My aim is that when i click on a specific patient on the recycleView row, it should take me to specific dynamic page layout containing specific details of the selected patient in the RecycleView without using the Screen Manager, the switching of dynamic pages.how can i go about this?
i have created a method called change_dynamic_Layout() for switching dynamic pages and it works fine when using the normal button to call it. I have used a print statement in the method to show if the method is executed or not. But when i use the SelectableButton,the print statement is executed but the statement for changing page-layout is not. No errors is shown and the dynamic page does not change. Here is the code try to run it and see what am talking about?
Demo.py
from kivy.app import App
from kivy.properties import ObjectProperty, StringProperty, ListProperty,
NumericProperty
from kivy.uix.behaviors import ButtonBehavior
from kivy.graphics import Color, Rectangle
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.gridlayout import GridLayout
from kivy.factory import Factory
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.lang import Builder
from kivy.uix.recycleview import RecycleView
from kivy.uix.recycleview.views import RecycleDataViewBehavior
from kivy.uix.label import Label
from kivy.uix.button import Button
from kivy.properties import BooleanProperty
from kivy.uix.recycleboxlayout import RecycleBoxLayout
from kivy.uix.recyclegridlayout import RecycleGridLayout
from kivy.uix.behaviors import FocusBehavior
from kivy.uix.recycleview.layout import LayoutSelectionBehavior
lost = Builder.load_file('Demo.kv')
class SelectableRecycleGridLayout(FocusBehavior, LayoutSelectionBehavior,
RecycleGridLayout):
''' Adds selection and focus behaviour to the view. '''
class SelectableButton(RecycleDataViewBehavior, Button):
''' Add selection support to the Label '''
index = None
selected = BooleanProperty(False)
selectable = BooleanProperty(True)
def refresh_view_attrs(self, rv, index, data):
''' Catch and handle the view changes '''
self.index = index
return super(SelectableButton, self).refresh_view_attrs(
rv, index, data)
def on_touch_down(self, touch):
''' Add selection on touch down '''
if super(SelectableButton, self).on_touch_down(touch):
return True
if self.collide_point(*touch.pos) and self.selectable:
return self.parent.select_with_touch(self.index, touch)
def apply_selection(self, rv, index, is_selected):
''' Respond to the selection of items in the view. '''
self.selected = is_selected
#selectablebutton to call the change_dynamic_Layout() method in patient class
def on_enter(self):
layout=Patient()
layout.change_dynamic_Layout()
class victor(BoxLayout):
pass
class Patient(Screen):
manage_prescription: ObjectProperty(None)
#Method to change the dynamic pagelayout
def change_dynamic_Layout(self):
layout = Factory.victor()
self.manage_prescription.clear_widgets()
self.manage_prescription.add_widget(layout)
print ('pressed')
class DemoApp(App):
title = 'Hospital Management System'
def build(self):
n= Patient()
return n
if __name__ == "__main__":
DemoApp().run()
demo.kv
<Patient>:
manage_prescription:manage_prescription
BoxLayout:
GridLayout :
cols:1
BoxLayout:
id:manage_prescription
orientation:'vertical'
BoxLayout:
size_hint_y:None
height:40
Button:
text:"NO."
font_size: 25
Button:
text:"Date"
font_size: 25
Button:
text:"Patient"
font_size: 25
Button:
text:"Doctor"
font_size: 25
on_press: root.change_dynamic_Layout()
BoxLayout:
RecycleView:
bar_width: 10
bar_color: 1, 0, 0, 1 # red
bar_inactive_color: 0, 0, 1, 1 # blue
#effect_cls: "ScrollEffect"
scroll_type: ['bars']
viewclass: 'SelectableButton'
data:[{'text': str(x)} for x in range(20)]
SelectableRecycleGridLayout:
cols:4
default_size: None, dp(56)
default_size_hint:1, None
size_hint_y: None
height: self.minimum_height
orientation: 'vertical'
multiselect: True
touch_multiselect: True
<victor>:
Label:
text:" Switched to specific page for patient's details"
<SelectableButton>:
# Draw a background to indicate selection
canvas.before:
Color:
rgba: (.0, 0.9, .1, .3) if self.selected else (1, 1, 1, 1)
Rectangle:
pos: self.pos
size: self.size
on_press: root.on_enter()
Any insight or help is much appreciated, thanks in advance.
The problem is that your on_enter method of the SelectableButton is creating a new Patient layout (Screen), and calling the change_dynamic_Layout method of that new Patient Screen. That newly created Patient Screen is not the one displayed in your app, so it has no effect on what you see. You actually want to call change_dynamic_Layout on the displayed Patient Screen. One way of doing this is to access it via App.get_running_app().root. So that your on_enter method can be changed to:
def on_enter(self):
#layout=Patient()
layout = App.get_running_app().root
layout.change_dynamic_Layout()
Here is the entire python file:
from kivy.app import App
from kivy.properties import ObjectProperty, StringProperty, ListProperty, NumericProperty
from kivy.uix.behaviors import ButtonBehavior
from kivy.graphics import Color, Rectangle
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.gridlayout import GridLayout
from kivy.factory import Factory
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.lang import Builder
from kivy.uix.recycleview import RecycleView
from kivy.uix.recycleview.views import RecycleDataViewBehavior
from kivy.uix.label import Label
from kivy.uix.button import Button
from kivy.properties import BooleanProperty
from kivy.uix.recycleboxlayout import RecycleBoxLayout
from kivy.uix.recyclegridlayout import RecycleGridLayout
from kivy.uix.behaviors import FocusBehavior
from kivy.uix.recycleview.layout import LayoutSelectionBehavior
lost = Builder.load_file('Demo.kv')
class SelectableRecycleGridLayout(FocusBehavior, LayoutSelectionBehavior,
RecycleGridLayout):
''' Adds selection and focus behaviour to the view. '''
class SelectableButton(RecycleDataViewBehavior, Button):
''' Add selection support to the Label '''
index = None
selected = BooleanProperty(False)
selectable = BooleanProperty(True)
def refresh_view_attrs(self, rv, index, data):
''' Catch and handle the view changes '''
self.index = index
return super(SelectableButton, self).refresh_view_attrs(
rv, index, data)
def on_touch_down(self, touch):
''' Add selection on touch down '''
if super(SelectableButton, self).on_touch_down(touch):
return True
if self.collide_point(*touch.pos) and self.selectable:
return self.parent.select_with_touch(self.index, touch)
def apply_selection(self, rv, index, is_selected):
''' Respond to the selection of items in the view. '''
self.selected = is_selected
#selectablebutton to call the change_dynamic_Layout() method in patient class
def on_enter(self):
#layout=Patient()
layout = App.get_running_app().root
layout.change_dynamic_Layout()
class victor(BoxLayout):
pass
class Patient(Screen):
manage_prescription: ObjectProperty(None)
#Method to change the dynamic pagelayout
def change_dynamic_Layout(self):
layout = Factory.victor()
self.manage_prescription.clear_widgets()
self.manage_prescription.add_widget(layout)
print ('pressed')
class DemoApp(App):
title = 'Hospital Management System'
def build(self):
n= Patient()
return n
if __name__ == "__main__":
DemoApp().run()
And here is the Demo.kv:
<Patient>:
manage_prescription:manage_prescription
BoxLayout:
GridLayout :
cols:1
BoxLayout:
id:manage_prescription
orientation:'vertical'
BoxLayout:
size_hint_y:None
height:40
Button:
text:"NO."
font_size: 25
Button:
text:"Date"
font_size: 25
Button:
text:"Patient"
font_size: 25
Button:
text:"Doctor"
font_size: 25
on_press: root.change_dynamic_Layout()
BoxLayout:
RecycleView:
bar_width: 10
bar_color: 1, 0, 0, 1 # red
bar_inactive_color: 0, 0, 1, 1 # blue
#effect_cls: "ScrollEffect"
scroll_type: ['bars']
viewclass: 'SelectableButton'
data:[{'text': str(x)} for x in range(20)]
SelectableRecycleGridLayout:
cols:4
default_size: None, dp(56)
default_size_hint:1, None
size_hint_y: None
height: self.minimum_height
orientation: 'vertical'
multiselect: True
touch_multiselect: True
<victor>:
Label:
text:" Switched to specific page for patient's details"
<SelectableButton>:
# Draw a background to indicate selection
canvas.before:
Color:
rgba: (.0, 0.9, .1, .3) if self.selected else (1, 1, 1, 1)
Rectangle:
pos: self.pos
size: self.size
on_press: root.on_enter()

Listview with popup on selection

I am trying to make a listview in which the selected buttons produce a popup with different information depending on which list button was selected. Any suggestions? Thank you
ListView has been deprecated since Kivy version 1.10.0. In the example below, we are using Recycleview.
Example
main.py
from kivy.app import App
from kivy.uix.recycleview import RecycleView
from kivy.uix.recycleview.views import RecycleDataViewBehavior
from kivy.uix.button import Button
from kivy.uix.recycleboxlayout import RecycleBoxLayout
from kivy.uix.behaviors import FocusBehavior
from kivy.uix.recycleview.layout import LayoutSelectionBehavior
from kivy.uix.popup import Popup
from kivy.properties import ListProperty, StringProperty, ObjectProperty
class MessageBox(Popup):
def popup_dismiss(self):
self.dismiss()
class SelectableRecycleBoxLayout(FocusBehavior, LayoutSelectionBehavior, RecycleBoxLayout):
""" Adds selection and focus behaviour to the view. """
selected_value = StringProperty('')
btn_info = ListProperty(['Button 0 Text', 'Button 1 Text', 'Button 2 Text'])
class SelectableButton(RecycleDataViewBehavior, Button):
""" Add selection support to the Label """
index = None
def refresh_view_attrs(self, rv, index, data):
""" Catch and handle the view changes """
self.index = index
return super(SelectableButton, self).refresh_view_attrs(rv, index, data)
def on_press(self):
self.parent.selected_value = 'Selected: {}'.format(self.parent.btn_info[int(self.id)])
def on_release(self):
MessageBox().open()
class RV(RecycleView):
rv_layout = ObjectProperty(None)
def __init__(self, **kwargs):
super(RV, self).__init__(**kwargs)
self.data = [{'text': "Button " + str(x), 'id': str(x)} for x in range(3)]
class TestApp(App):
title = "RecycleView Button Popup Demo"
def build(self):
return RV()
if __name__ == "__main__":
TestApp().run()
test.kv
#:kivy 1.10.0
<MessageBox>:
title: 'Popup Message Box'
size_hint: None, None
size: 400, 400
BoxLayout:
orientation: 'vertical'
Label:
text: app.root.rv_layout.selected_value
Button:
size_hint: 1, 0.2
text: 'OK'
on_press:
root.dismiss()
<SelectableButton>:
# Draw a background to indicate selection
canvas.before:
Color:
rgba: (0.0, 0.9, 0.1, 0.3)
Rectangle:
pos: self.pos
size: self.size
<RV>:
rv_layout: layout
viewclass: 'SelectableButton'
SelectableRecycleBoxLayout:
id: layout
default_size: None, dp(56)
default_size_hint: 0.1, None
size_hint_y: None
height: self.minimum_height
orientation: "vertical"
Output

Resources