How can I adjust the text height variable kivy?

I have a long text in kiwi. I want the dynamic height adjustment to depend on the amount of text.

My code is this.

import kivy from kivy.app import App from kivy.uix.label import Label from kivy.uix.gridlayout import GridLayout class DynamicHeight(App):y def build(self): grid = gl = GridLayout(cols=1) for i in range(3): l = Label(text='Text a longer line line line line line line line line', halign='left',text_size=(300, None)) grid.add_widget(l) return grid DynamicHeight().run() 

I want the label height or the height of the gridlayout settings line to match the amount of text.

+4
source share
4 answers

Despite the fact that there are already solutions, I feel that they do not use the kiwi method to do something, and that this method is cleaner. You need to bind text_size to the available width and bind the height of the widget to the rendering size.

 from kivy.app import App from kivy.uix.label import Label from kivy.uix.gridlayout import GridLayout from kivy.uix.floatlayout import FloatLayout class MyApp(App): def build(self): root = FloatLayout() b = GridLayout( cols=1, pos_hint={ 'center_x': .5, 'center_y': .5}, size_hint=(None, None), spacing=20, width=200) b.bind(minimum_height=b.setter('height')) root.add_widget(b) for text_lenght in range(0, 80, 20): l = Label( text='word ' * text_lenght, size_hint_y=None) l.bind(width=lambda s, w: s.setter('text_size')(s, (w, None))) l.bind(texture_size=l.setter('size')) b.add_widget(l) return root if __name__ == '__main__': MyApp().run() 
+4
source

text.size() method does not change the height attribute of the label. If the text is too long, it will overlap with the content below:

 from kivy.app import App from kivy.uix.label import Label from kivy.uix.button import Button from kivy.uix.gridlayout import GridLayout class DynamicHeight(App): def build(self): layout = GridLayout(cols=1, spacing=20) l = Label(text='! '*100, text_size=(10, None), size_hint_y=None, height=10) b = Button(text='...', size_hint_y=None) layout.add_widget(l) layout.add_widget(b) return layout DynamicHeight().run() 

You need to calculate the height of the text and set it manually with the height attribute. I do not know anything good and clean way to do this. Here is the dirty way:

 before = label._label.render() label.text_size=(300, None) after = label._label.render() label.height = (after[1]/before[1])*before[1] # ammount of rows * single row height 

Example:

 from kivy.app import App from kivy.uix.label import Label from kivy.uix.gridlayout import GridLayout from kivy.uix.scrollview import ScrollView class DynamicHeight(App): def build(self): layout = GridLayout(cols=1, size_hint_y=None, spacing=20) layout.bind(minimum_height=layout.setter('height')) for i in xrange(1, 20): l = Label(text='Text ' * (i*10), text_size=(300, None), size_hint_y=None) # calculating height here before = l._label.render() l.text_size=(300, None) after = l._label.render() l.height = (after[1]/before[1])*before[1] # ammount of rows * single row height # end layout.add_widget(l) root = ScrollView() root.add_widget(layout) return root DynamicHeight().run() 
0
source

I found a solution using thopiekar.

For those who need it. So far I have not found kivy without this method

 import kivy from kivy.app import App from kivy.uix.label import Label from kivy.uix.gridlayout import GridLayout from kivy.uix.boxlayout import BoxLayout from kivy.uix.button import Button class MultiLineLabel(Button): def __init__(self, **kwargs): super(MultiLineLabel, self).__init__( **kwargs) self.text_size = self.size self.bind(size= self.on_size) self.bind(text= self.on_text_changed) self.size_hint_y = None # Not needed here def on_size(self, widget, size): self.text_size = size[0], None self.texture_update() if self.size_hint_y == None and self.size_hint_x != None: self.height = max(self.texture_size[1], self.line_height) elif self.size_hint_x == None and self.size_hint_y != None: self.width = self.texture_size[0] def on_text_changed(self, widget, text): self.on_size(self, self.size) class DynamicHeight(App): def build(self): grid = GridLayout(cols=1,size_hint_x=None, width="300dp") l=['This Text very long, should add multiple lines, automatically. This Text very long, should add multiple lines, automatically', 'One line'] for i in l: l = MultiLineLabel(text=i) grid.add_widget(l) return grid DynamicHeight().run() 

And it works great !!!!!

0
source

Following tshirtman's answer, I created code to do the same in kv-lang. It may be a little clearer what is happening, since you do not need to parse the callback functions.

What happens is that the width of the label is set according to the layout, and the height is set to the size of the textured text. As the text string gets longer, the texture can only grow in height, which we can apply above by setting the height of the boxlayout to my_label.height.

 # -*- coding:utf8 -*- from kivy.lang import Builder from kivy.app import App from kivy.uix.label import Label from kivy.uix.boxlayout import BoxLayout from kivy.properties import StringProperty from kivy.core.window import Window Window.size = (400, 700) PLACEHOLDER_TEXT = u'''The bindings illustrated in tshirtman example are created automatically when using kv-lang. Notice how the "id: my_label" allows us to access the Label attributes in the BoxLayout height declaration.''' kv_string = """ <Example>: orientation: 'vertical' BoxLayout: # colored background for affected area: canvas.before: Color: rgba: 0.3, .4, .4, .6 Rectangle: pos: self.pos size: self.size size_hint_y: None height: my_label.height Label: id: my_label text: root.text font_size: '14dp' text_size: (self.width, None) size: self.texture_size valign: 'top' halign: 'left' BoxLayout: orientation: 'vertical' size_hint_y: 1 canvas.before: Color: rgba: 0.9, .0, .5, .6 Rectangle: pos: self.pos size: self.size TextInput: text: root.PLACEHOLDER_TEXT on_text: root.text = self.text text_size: self.size auto_indent: True Label: size_hint_y: None height: '50dp' text: 'String length: ' + str(len(root.text)) """ Builder.load_string( kv_string ) class Example (BoxLayout ): PLACEHOLDER_TEXT = PLACEHOLDER_TEXT text = StringProperty( ) def __init__(self, **kwargs): super( Example, self).__init__(**kwargs) class MyApp(App): def build(self): root = Example() return root MyApp().run() 
0
source

Source: https://habr.com/ru/post/1501049/


All Articles