1
votes

Is there a way to disable text wrapping in TextInput widget? That is, I still would like to have line breaks, but I don’t want to wrap words inside a paragraph. So it seems multiline=False is not what I'm looking for

Update: I mean there's "Word Wrap" option in Windows (windows 7 for example) Microsoft Notepad (Format - Word Wrap). I want to disable this option in kivy TextInput

1
Are you wanting horizontal scrolling in a TextInput? - John Anderson
@john-anderson I mean there's "Word Wrap" option in Windows (windows 7 for example) Microsoft Notepad (Format - Word Wrap). I want to disable this option in kivy TextInput - me2 beats
So what do you want the TextInput to show when you type in a line that is longer that the width of the TextInput? - John Anderson
the line continues to the right, you can navigate there to the right and back to the left (to the beginning of the line), just as Windows Notepad can do - me2 beats

1 Answers

3
votes

I don't do Windows, but that sounds like horizontal scrolling to me. The TextInput does horizontal scrolling by default if you set multiline to False, but not when multiline is True. So here is a hack to put a TextInput inside a ScrollView to provide horizontal scrolling when multiline is True:

from kivy.app import App
from kivy.lang import Builder
from kivy.properties import NumericProperty
from kivy.uix.scrollview import ScrollView
from kivy.uix.textinput import TextInput


class MyTextInput(TextInput):
    minimum_width = NumericProperty(1)

    def on_cursor(self, instance, newPos):
        # determine scroll position of parent ScrollView if multiline is True
        if not (isinstance(self.parent, ScrollView) and self.multiline):
            return super(MyTextInput, self).on_cursor(instance, newPos)
        if newPos[0] == 0:
            self.parent.scroll_x = 0
        else:
            over_width = self.width - self.parent.width
            if over_width <= 0.0:
                return super(MyTextInput, self).on_cursor(instance, newPos)
            view_start = over_width * self.parent.scroll_x
            view_end = view_start + self.parent.width
            offset = self.cursor_offset()
            desired_view_start = offset - 5
            desired_view_end = offset + self.padding[0] + self.padding[2] + self.cursor_width + 5
            if desired_view_start < view_start:
                self.parent.scroll_x = max(0, desired_view_start / over_width)
            elif desired_view_end > view_end:
                self.parent.scroll_x = min(1, (desired_view_end - self.parent.width) / over_width)
        return super(MyTextInput, self).on_cursor(instance, newPos)

    def on_text(self, instance, newText):
        # calculate minimum width
        width_calc = 0
        for line_label in self._lines_labels:
            width_calc = max(width_calc, line_label.width + 20)   # add 20 to avoid automatically creating a new line
        self.minimum_width = width_calc


theRoot = Builder.load_string('''
ScrollView:
    id: scroller
    effect_cls: 'ScrollEffect'  # keeps from scrolling to far
    MyTextInput:
        size_hint: (None, 1)
        width: max(self.minimum_width, scroller.width)
''')

class TI_in_SV(App):
    def build(self):
        return theRoot

TI_in_SV().run()

Note that MyTextInput extends TextInput.