英文:
How to make Labels in RecycleView change size according to texture size during runtime?
问题
我有一个RecycleView
,其中包含标签和一个MDSlider
,我在运行时使用它来更改这些标签的font_size
。我想知道是否可能将标签的大小与其texture_size
属性对齐。准确地说,每当我更改font_size
时,会导致标签的texture_size
溢出其当前大小,我希望增加标签的大小以适应文本。由于标签位于RecycleView
内部,我不确定应该如何解决这个问题。我最初将height
设置为RecycleBoxLayout
的self.minimum_height
,我认为它应该在过程中更新。我注意到我可以在运行时手动更改RecycleBoxLayout
的default_size
,但不确定应该如何传递标签的texture_size
来调整大小。我尝试使用on_size
和on_texture
方法传递属性并用于计算default_size
,但事情变得非常复杂,我总是最终在标签之间产生间隙。理想情况下,我希望使用标签大小/纹理的某种绑定解决方案(类似于我已经使用app.fontSize
实现的绑定),这样我就可以获得自动调整大小,因为任何手动计算RecycleView
属性及其后续更新都会显著减慢我的程序在测试Android时的速度。
有什么想法吗?
编辑:我没有提到,我只对高度调整感兴趣。宽度无关紧要。
from kivymd.app import MDApp
from kivy.lang import Builder
from kivy.uix.screenmanager import ScreenManager
from kivy.uix.screenmanager import Screen
from kivymd.uix.boxlayout import MDBoxLayout
from kivy.properties import StringProperty
kv = """
<MyLabel@MDLabel>:
font_size: app.fontSize
halign: 'center'
# Using these settings would be awesome, but cannot make it happen.
# Or there might be more elegant solution?
#size: self.texture_size
#size_hint_y: None
#text_size: self.width, None
<DailyService>:
day: ''
service: ''
MDGridLayout:
rows: 2
MyLabel:
id: firstLabelId
text: root.day
md_bg_color: app.theme_cls.accent_color
MyLabel:
id: secondLabelId
md_bg_color: app.theme_cls.primary_dark
text: root.service
<MainScreen>:
name: 'mainScreen'
myRv: rvId
MDRelativeLayout:
orientation: 'vertical'
MDRecycleView:
viewclass: 'DailyService'
id: rvId
rbl: rblId
RecycleBoxLayout:
id: rblId
default_size: None, dp(200)
default_size_hint: 1, None
size_hint_y: None
height: self.minimum_height
orientation: 'vertical'
MDSlider:
color: 'white'
orientation: 'horizontal'
size_hint: (0.2, 0.2)
pos_hint: {"x":0.4, "top": 1}
min: 10
value: 20
max: 150
on_value_normalized: root.fontSizeSlider(self.value)
MyScreenManager:
mainScreen: mainScreenId
MainScreen:
id: mainScreenId
"""
class DailyService(MDBoxLayout):
pass
class MainScreen(Screen):
def __init__(self, **kwargs):
super(MainScreen, self).__init__(**kwargs)
def fontSizeSlider(self, value):
app = MDApp.get_running_app()
app.fontSize = str(int(value)) + 'dp'
self.myRv.refresh_from_data()
class MyScreenManager(ScreenManager):
def __init__(self, **kwargs):
super(MyScreenManager, self).__init__(**kwargs)
class MyApp(MDApp):
fontSize = StringProperty('20dp')
def on_start(self):
data = []
for i in range(10):
data.append({'day': 'DAY\nDAY',
'service': 'SERVICE\nSERVICE'})
self.root.ids.mainScreenId.myRv.data = data
def build(self):
self.theme_cls.theme_style = 'Dark'
self.theme_cls.primary_palette = 'Blue'
self.theme_cls.accent_palette = 'Amber'
return Builder.load_string(kv)
if __name__ == '__main__':
MyApp().run()
英文:
I have a RecycleView
which consists of labels and a MDSlider
which I use to change font_size
of those labels during runtime. I'm wondering if it's possible to align labels' size to their texture_size
property. Precisely, whenever I change the font_size
which would cause label's texture_size
to overflow its current size, I would want to increase the label size so the text fits. Since labels live inside the RecycleView
, I'm not sure how should I approach the problem. I'm initially setting height
to self.minimum_height
of the RecycleBoxLayout
which I presume should be updated in the process. I noticed that I can manually change the RecycleBoxLayout's
default_size
during runtime, but not sure how exactly I should pass the texture_size
of the label to adjust the size. I tried with on_size
and on_texture
methods to pass the property and use to calculate default_size
, but things get really complicated and I always end up getting gaps between the labels. Ideally I would want the solution that uses some kind of binding of labels sizes/texture (similarly like I already have with the app.fontSize
) so I would get automatic resizing because any manual calculations of RecycleView
properties and it's consequential update significantly slows down my program in the end when testing on Android.
Any ideas?
EDIT: I haven't mentioned it, I'm only interested in the height resizing. Width doesn't matter.
from kivymd.app import MDApp
from kivy.lang import Builder
from kivy.uix.screenmanager import ScreenManager
from kivy.uix.screenmanager import Screen
from kivymd.uix.boxlayout import MDBoxLayout
from kivy.properties import StringProperty
kv = """
<MyLabel@MDLabel>:
font_size: app.fontSize
halign: 'center'
# Using these settings would be awesome, but cannot make it happen.
# Or there might be more elegant solution?
#size: self.texture_size
#size_hint_y: None
#text_size: self.width, None
<DailyService>:
day: ''
service: ''
MDGridLayout:
rows: 2
MyLabel:
id: firstLabelId
text: root.day
md_bg_color: app.theme_cls.accent_color
MyLabel:
id: secondLabelId
md_bg_color: app.theme_cls.primary_dark
text: root.service
<MainScreen>:
name: 'mainScreen'
myRv: rvId
MDRelativeLayout:
orientation: 'vertical'
MDRecycleView:
viewclass: 'DailyService'
id: rvId
rbl: rblId
RecycleBoxLayout:
id: rblId
default_size: None, dp(200)
default_size_hint: 1, None
size_hint_y: None
height: self.minimum_height
orientation: 'vertical'
MDSlider:
color: 'white'
orientation: 'horizontal'
size_hint: (0.2, 0.2)
pos_hint: {"x":0.4, "top": 1}
min: 10
value: 20
max: 150
on_value_normalized: root.fontSizeSlider(self.value)
MyScreenManager:
mainScreen: mainScreenId
MainScreen:
id: mainScreenId
"""
class DailyService(MDBoxLayout):
pass
class MainScreen(Screen):
def __init__(self, **kwargs):
super(MainScreen, self).__init__(**kwargs)
def fontSizeSlider(self, value):
app = MDApp.get_running_app()
app.fontSize = str(int(value)) + 'dp'
self.myRv.refresh_from_data()
class MyScreenManager(ScreenManager):
def __init__(self, **kwargs):
super(MyScreenManager, self).__init__(**kwargs)
class MyApp(MDApp):
fontSize = StringProperty('20dp')
def on_start(self):
data = []
for i in range(10):
data.append({'day': 'DAY\nDAY',
'service': 'SERVICE\nSERVICE'})
self.root.ids.mainScreenId.myRv.data = data
def build(self):
self.theme_cls.theme_style = 'Dark'
self.theme_cls.primary_palette = 'Blue'
self.theme_cls.accent_palette = 'Amber'
return Builder.load_string(kv)
if __name__ == '__main__':
MyApp().run()
答案1
得分: 1
from kivymd.app import MDApp
from kivy.lang import Builder
from kivy.uix.screenmanager import ScreenManager
from kivy.uix.screenmanager import Screen
from kivymd.uix.boxlayout import MDBoxLayout
from kivy.properties import StringProperty
kv = """
<MyLabel@MDLabel>:
font_size: app.fontSize
halign: 'center'
# Using these settings would be awesome, but cannot make it happen.
# Or there might be more elegant solution?
#size: self.texture_size
#size_hint_y: None
#text_size: self.width, None
<DailyService>:
day: ''
service: ''
MDGridLayout:
rows: 2
size_hint_y:None
height:app.MyHeight
MyLabel:
id: firstLabelId
text: root.day
md_bg_color: app.theme_cls.accent_color
MyLabel:
id: secondLabelId
md_bg_color: app.theme_cls.primary_dark
text: root.service
<MainScreen>:
name: 'mainScreen'
myRv: rvId
MDRelativeLayout:
orientation: 'vertical'
MDRecycleView:
viewclass: 'DailyService'
id: rvId
rbl: rblId
RecycleBoxLayout:
id: rblId
default_size: None, app.MyHeight
default_size_hint: 1, None
size_hint_y: None
height: self.minimum_height
orientation: 'vertical'
MDSlider:
color: 'white'
orientation: 'horizontal'
size_hint: (0.2, 0.2)
pos_hint: {"x":0.4, "top": 1}
min: 10
value: 20
max: 150
on_value_normalized: root.fontSizeSlider(self.value)
MyScreenManager:
mainScreen: mainScreenId
MainScreen:
id: mainScreenId
"""
class DailyService(MDBoxLayout):
pass
class MainScreen(Screen):
def __init__(self, **kwargs):
super(MainScreen, self).__init__(**kwargs)
def fontSizeSlider(self, value):
app = MDApp.get_running_app()
app.fontSize = str(int(value)) + 'dp'
app.MyHeight = str( int(value) * 10 ) + 'dp'
self.myRv.refresh_from_data()
class MyScreenManager(ScreenManager):
def __init__(self, **kwargs):
super(MyScreenManager, self).__init__(**kwargs)
class MyApp(MDApp):
fontSize = StringProperty('20dp')
MyHeight = StringProperty('200dp')
def on_start(self):
data = []
for i in range(10):
data.append({'day': 'DAY\nDAY',
'service': 'SERVICE\nSERVICE'})
self.root.ids.mainScreenId.myRv.data = data
def build(self):
self.theme_cls.theme_style = 'Dark'
self.theme_cls.primary_palette = 'Blue'
self.theme_cls.accent_palette = 'Amber'
return Builder.load_string(kv)
if __name__ == '__main__':
MyApp().run()
英文:
from kivymd.app import MDApp
from kivy.lang import Builder
from kivy.uix.screenmanager import ScreenManager
from kivy.uix.screenmanager import Screen
from kivymd.uix.boxlayout import MDBoxLayout
from kivy.properties import StringProperty
kv = """
<MyLabel@MDLabel>:
font_size: app.fontSize
halign: 'center'
# Using these settings would be awesome, but cannot make it happen.
# Or there might be more elegant solution?
#size: self.texture_size
#size_hint_y: None
#text_size: self.width, None
<DailyService>:
day: ''
service: ''
MDGridLayout:
rows: 2
size_hint_y:None
height:app.MyHeight
MyLabel:
id: firstLabelId
text: root.day
md_bg_color: app.theme_cls.accent_color
MyLabel:
id: secondLabelId
md_bg_color: app.theme_cls.primary_dark
text: root.service
<MainScreen>:
name: 'mainScreen'
myRv: rvId
MDRelativeLayout:
orientation: 'vertical'
MDRecycleView:
viewclass: 'DailyService'
id: rvId
rbl: rblId
RecycleBoxLayout:
id: rblId
default_size: None, app.MyHeight
default_size_hint: 1, None
size_hint_y: None
height: self.minimum_height
orientation: 'vertical'
MDSlider:
color: 'white'
orientation: 'horizontal'
size_hint: (0.2, 0.2)
pos_hint: {"x":0.4, "top": 1}
min: 10
value: 20
max: 150
on_value_normalized: root.fontSizeSlider(self.value)
MyScreenManager:
mainScreen: mainScreenId
MainScreen:
id: mainScreenId
"""
class DailyService(MDBoxLayout):
pass
class MainScreen(Screen):
def __init__(self, **kwargs):
super(MainScreen, self).__init__(**kwargs)
def fontSizeSlider(self, value):
app = MDApp.get_running_app()
app.fontSize = str(int(value)) + 'dp'
app.MyHeight = str( int(value) * 10 ) + 'dp'
self.myRv.refresh_from_data()
class MyScreenManager(ScreenManager):
def __init__(self, **kwargs):
super(MyScreenManager, self).__init__(**kwargs)
class MyApp(MDApp):
fontSize = StringProperty('20dp')
MyHeight = StringProperty('200dp')
def on_start(self):
data = []
for i in range(10):
data.append({'day': 'DAY\nDAY',
'service': 'SERVICE\nSERVICE'})
self.root.ids.mainScreenId.myRv.data = data
def build(self):
self.theme_cls.theme_style = 'Dark'
self.theme_cls.primary_palette = 'Blue'
self.theme_cls.accent_palette = 'Amber'
return Builder.load_string(kv)
if __name__ == '__main__':
MyApp().run()
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论