Home > front end >  Kivy RecycleView of Labels without clipping text or huge spaces between
Kivy RecycleView of Labels without clipping text or huge spaces between

Time:07-12

How can I make a RecycleView in a screenshot of the official documentation's demo showing a bunch of labels numbered "0" - "90" displaying in a scrollable window with white text and black background

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.

screenshot of the "demo with content" showing similar output as the previous screenshot, except now the label text isn't a mere integer, but a very long string. It's obvious that both the end of the string and the beginning of the string are not visible as they run-on before and after the viewport of the app. There is also a very big space between each line of text.

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.

screenshot of "demo with content and text_size" is similar to the previous screenshot, except the text of each line now wraps around on ~5 lines per label. Still, the beginning of the text of each line is truncated, but the end of the line is now visible. There is no longer a gap between each line.

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?

CodePudding user response:

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).

  • Related