I am using RecycleView for displaying a large number of data in sql. However the problem that i encounter is i can’t scroll to the bottom. It will just push back a little bit higher but i can’t scroll to the end. Here is the snippet of codes:
class MyBoxLayout(BoxLayout):
def __init__(self, **kwargs):
super().__init__(**kwargs)
self.orientation = "vertical"
self.size_hint_y = None
self.bind(minimum_height=self.setter('height'))
class CustomCard(BoxLayout, RecycleDataViewBehavior):
# Your properties and methods
fixed_height = NumericProperty(100)
event_id = NumericProperty()
widget_count = NumericProperty()
total_count = NumericProperty()
event_type = StringProperty()
reference_number = StringProperty()
remarks = StringProperty()
image_count = NumericProperty(0)
latitude = NumericProperty()
longitude = NumericProperty()
image_path = StringProperty(defaultvalue='')
created_at = StringProperty()
sent_at = StringProperty(defaultvalue='') # Add this line
sent_picture = NumericProperty(0)
index = 0
def update_card_height(self, *args):
total_height = 0
for child in self.children:
if child.size_hint_y is None:
total_height += child.height
self.height = total_height
# Force the RecycleView to refresh the view
if self.parent and hasattr(self.parent, 'refresh_from_data'):
self.parent.refresh_from_data()
def refresh_view_attrs(self, rv, index, data):
self.index = index
self.event_id = int(data.get('event_id', 0))
self.widget_count = data.get('widget_count', 0)
self.event_type = data.get('event_type', '')
self.reference_number = data.get('reference_number', '')
self.remarks = data.get('remarks', '')
self.image_count = data.get('image_count', 0)
self.latitude = float(data.get('latitude', 0.0))
self.longitude = float(data.get('longitude', 0.0))
self.image_path = data.get('image_path', '')
self.created_at = self.remarks = data.get('created_at', '')
self.sent_at = data.get('sent_at', '') or ''
self.sent_picture = int(data.get('event_id', 0))
super(CustomCard, self).refresh_view_attrs(rv, index, data)
Clock.schedule_once(self.update_card_height)
def on_touch_up(self, touch):
if self.collide_point(*touch.pos):
# Only call on_release if the touch was actually within the card
if touch.is_mouse_scrolling:
return False # Ignore scroll events
self.on_release()
return True
return super().on_touch_up(touch)
def on_release(self):
app = MDApp.get_running_app()
print(f"Event ID on release: {self.event_id}")
app.display_event_details(self.event_id)
app class:
class MainFunction(MDApp):
def add_main_widgets(self):
def fetch_data_thread():
events_data = self.fetch_data_from_db1()
self.update_ui_with_data(events_data)
self.cleanup_expired_events()
Thread(target=fetch_data_thread).start()
@mainthread
def update_ui_with_data(self, events_data):
event_buttons = self.sm.get_screen('main').ids.bottom_nav
card_list = self.sm.get_screen('main').ids.card_list
current_data = {card['event_id']: card for card in card_list.data}
self.original_data = [] # Store original data here
for event in events_data:
event_id = event.id
# Prepare the data for each card
card_data = {
'event_id': event_id,
'widget_count': 0,
'total_count': 0,
'event_type': event.event_type,
'reference_number': event.reference_number,
'remarks': event.remarks,
'image_count': event.image_count,
'latitude': event.latitude,
'longitude': event.longitude,
'created_at': event.created_at,
'sent_at': event.sent_at or '',
'sent_picture': event.sent_picture
}
# Add or update card data
if event_id in self.cards_dict:
self.cards_dict[event_id].update(card_data)
else:
self.cards_dict[event_id] = card_data
card_list.data.insert(0, card_data) # Add to card_list data
# Store the original data as the initial state
self.original_data = list(card_list.data)
# Calculate total count and update each card
total_count = len(card_list.data)
for index, card_data in enumerate(card_list.data):
card_data['widget_count'] = index + 1
card_data['total_count'] = total_count
event_buttons.action_items = [
MDActionBottomAppBarButton(icon="send-circle", on_release=lambda x: self.event_transfer()),
MDActionBottomAppBarButton(icon="image", on_release=lambda x: self.file_transfer()),
]
kv file:
<CustomCard>:
spacing: dp(8)
padding: dp(8)
# Add a canvas for background color
canvas.before:
Color:
rgba: (228/255, 225/255, 232/255, 1) # Set your desired background color here (e.g., white)
Rectangle:
size: self.size
pos: self.pos
MDFloatLayout:
size_hint: .01, 1
pos_hint: {"center_x": .02, "center_y": .5}
md_bg_color: "green" if root.sent_at else ("yellow" if root.latitude and root.longitude else "#EC1F26")
MyBoxLayout:
spacing: dp(1)
Label:
text: f"[{root.widget_count} of {root.total_count}]: {root.reference_number}"
font_size: "15sp"
color:"black"
bold: True
size_hint_y: None
height: self.texture_size[1]
text_size: self.width, None
Label:
text: "Remarks:"
bold: True
font_size:"14sp"
color:"#666666"
size_hint_y: None
height: self.texture_size[1] if root.remarks else 0
text_size: self.width, None
opacity: 1 if root.remarks else 0
Label:
text: root.remarks if root.remarks else "<None>"
font_size:"14sp"
color: (0, 0, 0, 1)
size_hint_y: None
height: self.texture_size[1] if root.remarks else 0
text_size: self.width, None
opacity: 1 if root.remarks else 0
MDButton:
style: 'text'
height: "15dp" if root.image_count > 0 else 0
size_hint_x: .3
opacity: 1 if root.image_count > 0 else 0
MDButtonIcon:
icon: 'image'
x: 1
theme_icon_color: "Custom"
icon_color: "black"
MDButtonText:
text: f"{root.image_count} Image(s) sent" if root.sent_picture == 1 else (f"{root.image_count} Image(s)" if root.image_count > 0 else "0 Image")
theme_text_color: "Custom"
text_color: "black"
font_style: "Body"
role: "medium"
Label:
text: f"Transmitted successfully: [color=#008000]{root.sent_at}[/color]" if root.sent_at else ("Status: Ready to transmit" if (root.latitude and root.longitude) else "Status: Location not found")
bold: True
font_size: "12sp"
color: "#666666"
size_hint_y: None
height: self.texture_size[1]
text_size: self.width, None
markup: True
AnchorLayout:
anchor_x: 'right'
anchor_y: 'top'
size_hint: None, None
size: 100, 50
pos_hint: {'right': 0.9, 'top': 1}
padding: [0, 5]
Label:
text: root.event_type
font_name: "f2icons/status.ttf"
color: "#ffff00"
font_size: "15sp"
MDScreen:
on_enter: app.set_bars_colors("#FFF200", "#FFFFFF", "Dark")
name: 'main'
md_bg_color: "#FFF200"
MDNavigationLayout:
MDScreenManager:
MDScreen:
MDBoxLayout:
orientation: 'vertical'
pos_hint: {"center_y": 0.36}
padding: [7, 10, 0, 0] # Add padding at the top to move the content down
TextInput:
id: search_bar
hint_text: "Search..."
height: '40dp' # Set a fixed height
size_hint_y: None # Disable size_hint_y to use fixed height
pos_hint: {"center_x": .5, "center_y": .5}
on_text: app.filter_cards(self.text)
width: '376dp' # Set a fixed width
size_hint_x: None # Disable size_hint_x to use fixed width
RecycleView:
id: card_list
pos_hint: {"center_y": 0.3}
size_hint_y: 1
viewclass: "CustomCard"
#effect_cls: "ScrollEffect"
do_scroll_x: False
RecycleBoxLayout:
orientation: 'vertical'
padding:dp(15)
spacing: dp(15)
orientation: 'vertical'
size_hint_y: None
height: self.minimum_height
default_size: 0, 36
default_size_hint: 1, None
key_size: 'cached_size'
MDBottomAppBar:
id: bottom_nav
#scroll_cls: card_list
#allow_hidden: True
theme_bg_color: "Custom"
MDFabBottomAppBarButton:
icon: "plus"
theme_bg_color: "Custom"
md_bg_color: "#FFF200"
theme_text_color: "Custom"
text_color: "black"
on_release: app.new_event()
I still can’t figure out. This only happens when i switch to RecycleView.