How can I make a RecycleView in a Kivy python app display all its labels without truncating the text contents of the label nor adding huge spaces in-between the labels?
I’m trying to display a very large amount of text in a Kivy (5+ MB) without causing it to lock-up. I think objectively the best solution here is to use a RecycleView with each line of the text in its own Label.
Official Documentation Demo
The example given in the official Kivy documentation about RecycleView is fine because the amount of text in the label is extremely short.
from kivy.app import App from kivy.lang import Builder from kivy.uix.recycleview import RecycleView Builder.load_string(''' <RV>: viewclass: 'Label' RecycleBoxLayout: default_size: None, dp(56) default_size_hint: 1, None size_hint_y: None height: self.minimum_height orientation: 'vertical' ''') class RV(RecycleView): def __init__(self, **kwargs): super(RV, self).__init__(**kwargs) self.data = [{'text': str(x)} for x in range(100)] class TestApp(App): def build(self): return RV() if __name__ == '__main__': TestApp().run()
Demo with content
But if we update the example above so that the text in the label is actually substantial, mimicking real-world text, then the contents of the label’s text gets truncated. And there’s a huge space in-between each label.
import random from kivy.app import App from kivy.lang import Builder from kivy.uix.recycleview import RecycleView Builder.load_string(''' <RV>: viewclass: 'Label' scroll_type: ['bars','content'] bar_width: dp(25) RecycleBoxLayout: default_size: None, dp(56) default_size_hint: 1, None size_hint_y: None height: self.minimum_height orientation: 'vertical' ''') class RV(RecycleView): def __init__(self, **kwargs): super(RV, self).__init__(**kwargs) self.data = [{'text': str(self.get_random())} for x in range(100)] def get_random(self): # generate some random ASCII content random_ascii = ''.join( [random.choice('0123456789abcdefghijklnmnoqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ') for i in range(0,900)] ) random_ascii = 'START|' + random_ascii + '|END' print( random_ascii) return random_ascii class TestApp(App): def build(self): return RV() if __name__ == '__main__': TestApp().run()
Demo with content and ‘text_size’
I’ve tried setting the text_size
of the Label. That certainly displays much more of the text, but it’s still not showing all of the text in each Label.
In this example, the gap between each label is now gone.
import random from kivy.app import App from kivy.lang import Builder from kivy.uix.recycleview import RecycleView Builder.load_string(''' <MyLabel@Label>: text_size: self.size <RV>: viewclass: 'MyLabel' scroll_type: ['bars','content'] bar_width: dp(25) RecycleBoxLayout: default_size: None, dp(56) default_size_hint: 1, None size_hint_y: None height: self.minimum_height orientation: 'vertical' ''') class RV(RecycleView): def __init__(self, **kwargs): super(RV, self).__init__(**kwargs) self.data = [{'text': str(self.get_random())} for x in range(100)] def get_random(self): # generate some random ASCII content random_ascii = ''.join( [random.choice('0123456789abcdefghijklnmnoqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ') for i in range(0,900)] ) random_ascii = 'START|' + random_ascii + '|END' print( random_ascii) return random_ascii class TestApp(App): def build(self): return RV() if __name__ == '__main__': TestApp().run()
How can I display a vertical
RecycleView of Labels such that the text contents of the Labels is not truncated, and there is no extra padding/margin between each row of Labels?
Advertisement
Answer
If you want the Label
to stretch up as its text content, you can bind its width to its texture
width. This will enable you to scroll horizontally within RecycleView
. Again if you want to scroll vertically, you need to explicitly specify the height of each content (here Label
).
Here’s a modified version (of the last one) of your kvlang
,
<MyLabel@Label>: size_hint_x: None width: self.texture_size[0] # Canvas added for visual purpose. canvas.before: Color: rgb: 0.5, 0.5, 1 Rectangle: size: self.size pos: self.pos <RV>: viewclass: 'MyLabel' scroll_type: ['bars','content'] bar_width: dp(25) RecycleBoxLayout: spacing: dp(1) # Adjust to your need (atyn). padding: dp(2) # atyn. default_size: None, dp(20) # atyn. default_size_hint: None, None size_hint: None, None size: self.minimum_size orientation: 'vertical'
Depending on the sample size (due to hardware) it may or may not be able to render the text. If so, try with smaller sample size (like in your examples 500/600 instead of 900).