Search code examples
pythonkivy

Kivy self sizing TextInput (multiline)


Good evening!

I am trying to make a TextInput widget increase in height when the text goes on the next line. The thing is, this is inside an image and it has to scale as well. Here is what I'm talking about:

On a side note, everytime I type a certain text, the space goes on the next line like this:

The quick brown fox jumped over   |
the lazy dog.  The quick brown fox|
 jumped over the lazy dog.  The   |
sly brown fox jumped over the lazy|

Is there a way to avoid this?

Here is the part of the file.kv file with the problem:

#:kivy 1.10.0

<Manager>:
    Chat:
        name: 'chat'
<Chat>:
    canvas:
        Rectangle:
            pos: self.x, 0
            size: self.width, self.height

    Button:
        id: stgs
        background_down: './icons/settings-press.png'
        background_normal: './icons/settings.png'
        border: 0, 0, 0, 0
        always_release: True
        right: root.right - 20
        top: root.top - 10
        size: 40, 40
        size_hint: None, None
        on_release:
            root.manager.transition.direction = 'down'
            root.manager.current = 'settings'

    Button:
        id: bck
        background_down: './icons/back-press.png'
        background_normal: './icons/back.png'
        border: 0, 0, 0, 0
        x: root.x + 20
        top: root.top - 10
        size: 40, 40
        size_hint: None, None
        on_release:
            root.manager.transition.direction = 'right'
            root.manager.current = 'main'

    BoxLayout:
        orientation: 'horizontal'
        padding: 10, 10, 10, 10
        cols: 2
        Image:
            id: inpimg
            source: './icons/user_inp.png'
            x: root.x + 10
            y: root.y + 10
            size: root.width - 40, 40
            size_hint: 0.9, None
            allow_stretch: True
            keep_ratio: False
            TextInput:
                id: usrinp
                valign: 'middle'
                halign: 'left'
                font_size: 16
                multiline: True
                x: root.ids['inpimg'].x + 10
                y: root.ids['inpimg'].y + 5
                background_color: 0, 0, 0, 0
                size: root.width - 80, 33

        Button:
            id: post
            foreground_color: 0, 0, 0, 0
            background_down: './icons/type1-press.png'
            background_normal: './icons/type1.png'
            border: 0, 0, 0, 0
            size: 40, 40
            x: root.width * 14/17 + 5
            y: root.y + 20
            size_hint: None, None

Here is the minimal .py file:

from kivy.app import App
from kivy.uix.screenmanager import ScreenManager, Screen


class Chat(Screen):
    pass

class Manager(ScreenManager):
    pass

class FileApp(App):
    def build(self):
        return Manager()


if __name__ == "__main__":
    FileApp().run()

If you know a better way of putting a text box inside an image, please let me know! This method that I thought of seems kinda forced...

Optional question: Is it possible to use '.gmd' files with kivy?

Thank you in advance!


Solution

  • Simple example code with a multiline TextInput whose height is dynamically modified according to its text content:

    textinputtextsize.kv file

    <TextInputTextSize>:
        canvas.before:
            Color:
                rgb: [0.22,0.22,0.22]
            Rectangle:
                pos: self.pos
                size: self.size
        orientation: "vertical"
        textInputSingleLine: txt_input_singleline
        textInputMultiline: txt_input_multiline
    
        GridLayout:
            cols: 1
            canvas.before:
                Rectangle:
                    pos: self.pos
                    size: self.size
            TextInput:
                id: txt_input_singleline
                size_hint_y: None
                height: "28dp"
                focus: True
                multiline: False
                on_text_validate: root.submitRequest() # ENTER triggers root.submitRequest()
            TextInput:
                id: txt_input_multiline
                text: "Audio - ET L'UNIVERS DISPARAÎTRA La nature   \nillusoire de notre réalité et le pouvoir \ntranscendant du véritable pardon \n+ commentaires de Gary Renard"
                size_hint_y: None
                height: (len(txt_input_multiline._lines)+1) * txt_input_multiline.line_height
    

    py file

    from kivy.app import App
    from kivy.properties import ObjectProperty
    from kivy.uix.boxlayout import BoxLayout
    
    
    class TextInputTextSize(BoxLayout):
        textInput = ObjectProperty()
        textInputMultiline = ObjectProperty()
    
        def submitRequest(self):
            # Get the request from the TextInput
            textInputTxt = self.textInputSingleLine.text
            self.textInputMultiline.text += '\n' + textInputTxt
    
    class TextInputTextSizeApp(App):
        def build(self):
            return TextInputTextSize()
    
    if __name__ == '__main__':
        TextInputTextSizeApp().run()