问题
I'm having issues building a Kivy dropdown with word wrapping enabled for the text, such that the button widgets size accordingly to accommodate the full text.
I have followed guidance from the stack overflow thread below and similar blog post that is also linked.
Wrapping the text of a Kivy Label
https://blog.kivy.org/2014/07/wrapping-text-in-kivys-label/
The text wraps as expected, however as the text string gets longer, there is an increasing amount of "padding" above and below the text when the button is rendered. I am unsure of what is causing this and would like to eliminate this effect.
Updated: (Edited code to be more concise to the issue. Edited image to match)
The "extra padding" is not related to the length of text, but rather the index of the loop and/or widget count added to the dropdown.
Further editing this line of code:
btn2 = WrapButton(text=('|' + str('long text..is long...%d' % (21-index) * index) + '|') , size_hint=(1,None))
To:
btn2 = WrapButton(text=('|' + str('long text..is long...%d' % (21-index) * index) + '|') , size_hint=(None,None),width=700)
(set size_hint=(none,none) rather than (1,none) and add width=700)
Eliminates the issue. I can not wrap my head around what is causing this behavior. The edited code loses the automatic width sizing for the button, and I can't imagine how a width size_hint is causing vertical "padding".
Screenshot showing issue
This code demonstrates the issue:
from kivy.uix.button import Button
from kivy.uix.dropdown import DropDown
from kivy.uix.boxlayout import BoxLayout
from kivy.base import runTouchApp
from kivy.lang import Builder
Builder.load_string('''
<WrapButton>:
halign: "center"
valign: "center"
font_size: 20
size_hint_y: None
text_size : self.size
height: self.texture_size[1]
''')
class WrapButton(Button):
pass
dropdown2 = DropDown()
layout = BoxLayout(padding=0,orientation='vertical')
mainbutton2 = WrapButton(text='Select...', size_hint=(1, None),height=95,pos_hint={'center_x': .5, 'center_y': 0})
mainbutton2.bind(on_release=dropdown2.open)
layout.add_widget(mainbutton2)
for index in range(20):
btn2 = WrapButton(text=('|' + str('long text..is long...%d' % (21-index) * index) + '|') , size_hint=(1,None))
btn2.bind(on_release=lambda btn2: dropdown2.select(btn2.text))
dropdown2.add_widget(btn2)
dropdown2.bind(on_select=lambda instance, x: setattr(mainbutton2, 'text', x))
runTouchApp(layout)
screenshot
Update: The answer accepted below is resulting in artifacts on Android. I am working to test on other devices to rule out the device itself. Any input from the community here would be appreciated!
Artifacts..broken Kivy install?
回答1:
The solution is to replace text_size : self.size
with text_size : self.width, None
. Please refer to the example and output for details.
Example
main.py
from kivy.uix.button import Button
from kivy.uix.dropdown import DropDown
from kivy.uix.boxlayout import BoxLayout
from kivy.base import runTouchApp
from kivy.lang import Builder
Builder.load_string('''
<WrapButton>:
halign: "center"
valign: "center"
font_size: 20
size_hint_y: None
text_size : self.width, None
height: self.texture_size[1]
''')
class WrapButton(Button):
pass
dropdown2 = DropDown()
layout = BoxLayout(padding=0, orientation='vertical')
mainbutton2 = WrapButton(text='Select...', size_hint=(1, None), height=95, pos_hint={'center_x': .5, 'center_y': 0})
mainbutton2.bind(on_release=dropdown2.open)
layout.add_widget(mainbutton2)
for index in range(20):
btn2 = WrapButton(text=('|' + str('long text..is long...%d' % (21-index) * index) + '|'), size_hint=(1, None))
btn2.bind(on_release=lambda btn2: dropdown2.select(btn2.text))
dropdown2.add_widget(btn2)
dropdown2.bind(on_select=lambda instance, x: setattr(mainbutton2, 'text', x))
runTouchApp(layout)
Output
来源:https://stackoverflow.com/questions/50416284/kivy-sizing-buttons-to-fit-wrapped-text-within-dropdown