How to center a text horizontally in a TextInput in Kivy?
I have the following screen:
But I want to centralize my text like this:
And this is part of my kv language:
BoxLayout: orientation: 'vertical'Label:markup: Truetext: '[b] Type something... [/b]'size_hint: 1, 0.6size: self.parent.size[0], 200font_size: self.size[0] * 0.1text_size: self.sizehalign: 'center'valign: 'middle'canvas.before:Color:rgb: 0, 0, 204Rectangle:pos: self.possize: self.sizeTextInput:focus: True
How can I center my TextInput's text?
Afaik, there's no such thing as aligning in the same way as it's in Label
, however, you can use padding
to push the position wherever you want. Keep in mind that changing the size of text will affect the centering, therefore you'll need to recalculate on change of size (e.g. when working with multiple devices, sizes, etc).
Or there could be even a workaround, where you could make TextInput
invisible, use Label
to fetch touch event to trigger TextInput
(which would open keyboard) and change Label
's text on change of TextInput
's text property. You'll lose the possibility to work with cursor this way and you'll need to handle wrapping text.
Example:
from kivy.app import App
from kivy.lang import Builder
from kivy.uix.boxlayout import BoxLayout
Builder.load_string('''
<Test>:TextInput:text: 't'font_size: 60# left, rightpadding_x:[self.center[0] - self._get_text_width(max(self._lines, key=len), self.tab_width, self._label_cached) / 2.0,0] if self.text else [self.center[0], 0]# top, bottompadding_y: [self.height / 2.0 - (self.line_height / 2.0) * len(self._lines), 0]
''')
class Test(BoxLayout):pass
class TestApp(App):def build(self):return Test()
TestApp().run()
self._get_text_width(...)
is obviously a method of a TextInput
. It's working with the core of the widget so it might be unstable (first example I posted was buggy because of my mistake) ^^
Now if padding_x
's values padd from left
and right
, you'll need only the left side (the difference is only in using addition and substraction in the right place), so let's do that:
- get the longest substring in the
TextInput
- get its width (because it's not consistent!) via the fancy method
- substract from
center[0]
coordinate
When we've already centered the X axis, let's go to the Y. padding_y
's values are top
and bottom
:
- padd down the half of the widget's
height
- get a half of a height of a single line
- multiply the number by the count of lines that are in
TextInput
- substract the number from
self.height / 2.0
- bottom is
0
, we don't care about it
Note: max()
expects some arguments and if there's no text
, max()
will raise its voice. We'll shut it with an alternative left padding for padding_x
using only the center:
<padding_x with max> if self.text else [self.center[0], 0]