I made a recycleview list of custom cards. For each card i want to pass a custom object called "show", its type is "Content". The class of custom card is "StreamingShowCard". I can't create the card by KVlang because its class contains some pytho methods.
This is the code:
from kivymd.app import MDApp
from kivy.lang import Builder
from kivymd.uix.behaviors import RoundedRectangularElevationBehavior
from kivymd.uix.card import MDCard
from kivy.properties import StringProperty
from kivy.uix.behaviors import ButtonBehavior
from kivymd.uix.list import OneLineIconListItem
from kivymd.uix.tab import MDTabsBase
from kivymd.uix.floatlayout import MDFloatLayout
from kivymd.uix.boxlayout import MDBoxLayout
from kivymd.uix.label import MDLabel
from kivymd.uix.gridlayout import MDGridLayout
from kivymd.uix.fitimage import FitImage
from kivy.uix.image import AsyncImage
from kivymd.uix.button import MDFlatButton
#import datetime
from datetime import datetime
from kivy.uix.image import Image
from kivymd.uix.dialog import MDDialog
from kivymd.uix.screen import MDScreen
from kivymd.uix.responsivelayout import MDResponsiveLayout
from kivymd.uix.progressbar import MDProgressBar
from kivy.clock import Clock
from kivymd.uix.button import MDIconButton
from kivymd.uix.list import IconLeftWidget
from kivymd.uix.recycleview import MDRecycleView
from kivy import properties
KV = '''
<Cover>:
<StreamingShowCard>:
show: root.show
MDScreen:
MDRecycleView:
size_hint_y: 1
size_hint_x: 1
viewclass: 'StreamingShowCard'
id: rv
MDRecycleGridLayout:
cols: 2
height: self.minimum_height
size_hint_y: None
row_default_height: '250dp'
row_force_default: True
padding: dp(10)
spacing: dp(10)
MDFloatingActionButton:
id: fab
icon: "plus"
pos_hint: {"center_x": .5, "center_y": .1}
on_release: app.add_item()
'''
class MD3Card(MDCard, RoundedRectangularElevationBehavior):
'''Implements a material design v3 card.'''
text = StringProperty()
class Content: #eg: film found
name = ""
url = ""
platform = ""
imageUrl = ""
Image = False
#free = False
def __init__(self, name, url, platform, imageUrl):
self.name = name
self.url = url
self.platform = platform
self.imageUrl = imageUrl
class StreamingShowCard(MD3Card):
#show = None #the object of Content class attached to the
show = properties.ObjectProperty()
def __init__(self, **kwargs):
super(StreamingShowCard, self).__init__(**kwargs)
self.__set_cardGraphic()
self.image = Cover(size_hint_min_y=0.7, source="https://kivy.org/doc/stable/_static/logo-kivy.png", opacity= 100 if True else 0, radius= ["10dp", "10dp", "0dp", "0dp"])
grid1 = MDGridLayout(cols=1, size_hint_x=1, size_hint_y=1, rows=3)
grid1.add_widget(self.image)
grid1.add_widget(MDLabel(text=self.show, size_hint_y = 0.3, font_style='Subtitle2', halign='left', valign='middle'))
box1 = MDBoxLayout(orientation = "horizontal", size_hint_x=1, size_hint_y=0.2)
box1.add_widget(MDLabel(text="self.show.platform", size_hint_y = 1, size_hint_x=0.8, theme_text_color="Secondary", font_style='Caption', halign='left', valign='middle'))
grid1.add_widget(box1)
self.add_widget(grid1)
def __set_cardGraphic(self):
self.md_bg_color = "#18222c"
#self.size_hint_y = None
self.elevation = 10
self.padding = "1dp"
self.size_hint_x = 1
self.radius = "10dp"
self.ripple_behavior = True
self.on_press = self.cardPress
def cardPress(self, *args):
dialog = MDDialog(
title = "Aprire la pagina in un browser?",
text = "Text",#self.show.name,
size_hint = (0.8, 0.8),
auto_dismiss = False,
buttons=[
MDFlatButton(text="No", text_color=self.theme_cls.primary_color, on_release=lambda x: dialog.dismiss()),
MDFlatButton(text="Si", text_color=self.theme_cls.primary_color, on_release=lambda x: yesClick())
]
)
dialog.open()
def yesClick():
#openUrl(self.show.url)
dialog.dismiss(force=True)
def loadImage(self, *args):
if not self.show.Image:
self.show.loadImage(True)
self.image.source = self.show.imageUrl
self.image.opacity = 100
self.image.reload()
class Cover(AsyncImage, FitImage):
pass
class MainApp(MDApp):
def build(self):
return Builder.load_string(KV)
def add_item(self):
for i in range(100):
self.root.ids.rv.data.append({
"show": Content("name", "www.google.com", "platform", "https://kivy.org/doc/stable/_static/logo-kivy.png")
})
MainApp().run()
If the recycleview's viewclass is a Label i can pass the text directly from main by appending dict to RV data, but whit this custom class of recycle view i cannot pass Content to show property. Is it possible to populate the RecycleView by the main?
Couldn't get your code to run, but if you want to use an ObjectProperty
in the data
of a RecycleView
, you need to handle it a bit differently. Here is an example of using an ObjectProperty
in the data
:
from kivy.app import App
from kivy.lang import Builder
from kivy.properties import ObjectProperty, StringProperty
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.image import Image
from kivy.uix.recycleview import RecycleView
Builder.load_string('''
<MyObject>:
size_hint_y: None
height: 100
Label:
id: label
text: root.text # uses the text StringProperty
size_hint: None, None
size: 200, 100
<RV>:
viewclass: 'MyObject'
RecycleBoxLayout:
default_size: None, 100
default_size_hint: 1, None
size_hint_y: None
height: self.minimum_height
orientation: 'vertical'
''')
class MyObject(BoxLayout):
show = ObjectProperty(None)
text = StringProperty('Abba')
def on_show(self, instance, new_obj):
# handle the ObjectProperty named show
if new_obj.parent:
# remove this obj from any other MyObject instance
new_obj.parent.remove_widget(new_obj)
for ch in self.children:
if isinstance(ch, Image):
# remove any previous obj instances
self.remove_widget(ch)
break
# add the new obj to this MyObject instance
self.add_widget(new_obj)
class RV(RecycleView):
def __init__(self, **kwargs):
super(RV, self).__init__(**kwargs)
self.data = [{'text': str(x),
'show': Image(source='tester.png', size_hint=(None, None), size=(100, 100),
allow_stretch=True, keep_ratio=True)}
for x in range(100)]
class TestApp(App):
def build(self):
return RV()
if __name__ == '__main__':
TestApp().run()