如何在运行时根据纹理大小调整RecycleView中的标签大小?

huangapple go评论112阅读模式
英文:

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设置为RecycleBoxLayoutself.minimum_height,我认为它应该在过程中更新。我注意到我可以在运行时手动更改RecycleBoxLayoutdefault_size,但不确定应该如何传递标签的texture_size来调整大小。我尝试使用on_sizeon_texture方法传递属性并用于计算default_size,但事情变得非常复杂,我总是最终在标签之间产生间隙。理想情况下,我希望使用标签大小/纹理的某种绑定解决方案(类似于我已经使用app.fontSize实现的绑定),这样我就可以获得自动调整大小,因为任何手动计算RecycleView属性及其后续更新都会显著减慢我的程序在测试Android时的速度。

有什么想法吗?

编辑:我没有提到,我只对高度调整感兴趣。宽度无关紧要。

  1. from kivymd.app import MDApp
  2. from kivy.lang import Builder
  3. from kivy.uix.screenmanager import ScreenManager
  4. from kivy.uix.screenmanager import Screen
  5. from kivymd.uix.boxlayout import MDBoxLayout
  6. from kivy.properties import StringProperty
  7. kv = """
  8. <MyLabel@MDLabel>:
  9. font_size: app.fontSize
  10. halign: 'center'
  11. # Using these settings would be awesome, but cannot make it happen.
  12. # Or there might be more elegant solution?
  13. #size: self.texture_size
  14. #size_hint_y: None
  15. #text_size: self.width, None
  16. <DailyService>:
  17. day: ''
  18. service: ''
  19. MDGridLayout:
  20. rows: 2
  21. MyLabel:
  22. id: firstLabelId
  23. text: root.day
  24. md_bg_color: app.theme_cls.accent_color
  25. MyLabel:
  26. id: secondLabelId
  27. md_bg_color: app.theme_cls.primary_dark
  28. text: root.service
  29. <MainScreen>:
  30. name: 'mainScreen'
  31. myRv: rvId
  32. MDRelativeLayout:
  33. orientation: 'vertical'
  34. MDRecycleView:
  35. viewclass: 'DailyService'
  36. id: rvId
  37. rbl: rblId
  38. RecycleBoxLayout:
  39. id: rblId
  40. default_size: None, dp(200)
  41. default_size_hint: 1, None
  42. size_hint_y: None
  43. height: self.minimum_height
  44. orientation: 'vertical'
  45. MDSlider:
  46. color: 'white'
  47. orientation: 'horizontal'
  48. size_hint: (0.2, 0.2)
  49. pos_hint: {"x":0.4, "top": 1}
  50. min: 10
  51. value: 20
  52. max: 150
  53. on_value_normalized: root.fontSizeSlider(self.value)
  54. MyScreenManager:
  55. mainScreen: mainScreenId
  56. MainScreen:
  57. id: mainScreenId
  58. """
  59. class DailyService(MDBoxLayout):
  60. pass
  61. class MainScreen(Screen):
  62. def __init__(self, **kwargs):
  63. super(MainScreen, self).__init__(**kwargs)
  64. def fontSizeSlider(self, value):
  65. app = MDApp.get_running_app()
  66. app.fontSize = str(int(value)) + 'dp'
  67. self.myRv.refresh_from_data()
  68. class MyScreenManager(ScreenManager):
  69. def __init__(self, **kwargs):
  70. super(MyScreenManager, self).__init__(**kwargs)
  71. class MyApp(MDApp):
  72. fontSize = StringProperty('20dp')
  73. def on_start(self):
  74. data = []
  75. for i in range(10):
  76. data.append({'day': 'DAY\nDAY',
  77. 'service': 'SERVICE\nSERVICE'})
  78. self.root.ids.mainScreenId.myRv.data = data
  79. def build(self):
  80. self.theme_cls.theme_style = 'Dark'
  81. self.theme_cls.primary_palette = 'Blue'
  82. self.theme_cls.accent_palette = 'Amber'
  83. return Builder.load_string(kv)
  84. if __name__ == '__main__':
  85. 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&#39;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.

  1. from kivymd.app import MDApp
  2. from kivy.lang import Builder
  3. from kivy.uix.screenmanager import ScreenManager
  4. from kivy.uix.screenmanager import Screen
  5. from kivymd.uix.boxlayout import MDBoxLayout
  6. from kivy.properties import StringProperty
  7. kv = &quot;&quot;&quot;
  8. &lt;MyLabel@MDLabel&gt;:
  9. font_size: app.fontSize
  10. halign: &#39;center&#39;
  11. # Using these settings would be awesome, but cannot make it happen.
  12. # Or there might be more elegant solution?
  13. #size: self.texture_size
  14. #size_hint_y: None
  15. #text_size: self.width, None
  16. &lt;DailyService&gt;:
  17. day: &#39;&#39;
  18. service: &#39;&#39;
  19. MDGridLayout:
  20. rows: 2
  21. MyLabel:
  22. id: firstLabelId
  23. text: root.day
  24. md_bg_color: app.theme_cls.accent_color
  25. MyLabel:
  26. id: secondLabelId
  27. md_bg_color: app.theme_cls.primary_dark
  28. text: root.service
  29. &lt;MainScreen&gt;:
  30. name: &#39;mainScreen&#39;
  31. myRv: rvId
  32. MDRelativeLayout:
  33. orientation: &#39;vertical&#39;
  34. MDRecycleView:
  35. viewclass: &#39;DailyService&#39;
  36. id: rvId
  37. rbl: rblId
  38. RecycleBoxLayout:
  39. id: rblId
  40. default_size: None, dp(200)
  41. default_size_hint: 1, None
  42. size_hint_y: None
  43. height: self.minimum_height
  44. orientation: &#39;vertical&#39;
  45. MDSlider:
  46. color: &#39;white&#39;
  47. orientation: &#39;horizontal&#39;
  48. size_hint: (0.2, 0.2)
  49. pos_hint: {&quot;x&quot;:0.4, &quot;top&quot;: 1}
  50. min: 10
  51. value: 20
  52. max: 150
  53. on_value_normalized: root.fontSizeSlider(self.value)
  54. MyScreenManager:
  55. mainScreen: mainScreenId
  56. MainScreen:
  57. id: mainScreenId
  58. &quot;&quot;&quot;
  59. class DailyService(MDBoxLayout):
  60. pass
  61. class MainScreen(Screen):
  62. def __init__(self, **kwargs):
  63. super(MainScreen, self).__init__(**kwargs)
  64. def fontSizeSlider(self, value):
  65. app = MDApp.get_running_app()
  66. app.fontSize = str(int(value)) + &#39;dp&#39;
  67. self.myRv.refresh_from_data()
  68. class MyScreenManager(ScreenManager):
  69. def __init__(self, **kwargs):
  70. super(MyScreenManager, self).__init__(**kwargs)
  71. class MyApp(MDApp):
  72. fontSize = StringProperty(&#39;20dp&#39;)
  73. def on_start(self):
  74. data = []
  75. for i in range(10):
  76. data.append({&#39;day&#39;: &#39;DAY\nDAY&#39;,
  77. &#39;service&#39;: &#39;SERVICE\nSERVICE&#39;})
  78. self.root.ids.mainScreenId.myRv.data = data
  79. def build(self):
  80. self.theme_cls.theme_style = &#39;Dark&#39;
  81. self.theme_cls.primary_palette = &#39;Blue&#39;
  82. self.theme_cls.accent_palette = &#39;Amber&#39;
  83. return Builder.load_string(kv)
  84. if __name__ == &#39;__main__&#39;:
  85. MyApp().run()

答案1

得分: 1

  1. from kivymd.app import MDApp
  2. from kivy.lang import Builder
  3. from kivy.uix.screenmanager import ScreenManager
  4. from kivy.uix.screenmanager import Screen
  5. from kivymd.uix.boxlayout import MDBoxLayout
  6. from kivy.properties import StringProperty
  7. kv = """
  8. <MyLabel@MDLabel>:
  9. font_size: app.fontSize
  10. halign: 'center'
  11. # Using these settings would be awesome, but cannot make it happen.
  12. # Or there might be more elegant solution?
  13. #size: self.texture_size
  14. #size_hint_y: None
  15. #text_size: self.width, None
  16. <DailyService>:
  17. day: ''
  18. service: ''
  19. MDGridLayout:
  20. rows: 2
  21. size_hint_y:None
  22. height:app.MyHeight
  23. MyLabel:
  24. id: firstLabelId
  25. text: root.day
  26. md_bg_color: app.theme_cls.accent_color
  27. MyLabel:
  28. id: secondLabelId
  29. md_bg_color: app.theme_cls.primary_dark
  30. text: root.service
  31. <MainScreen>:
  32. name: 'mainScreen'
  33. myRv: rvId
  34. MDRelativeLayout:
  35. orientation: 'vertical'
  36. MDRecycleView:
  37. viewclass: 'DailyService'
  38. id: rvId
  39. rbl: rblId
  40. RecycleBoxLayout:
  41. id: rblId
  42. default_size: None, app.MyHeight
  43. default_size_hint: 1, None
  44. size_hint_y: None
  45. height: self.minimum_height
  46. orientation: 'vertical'
  47. MDSlider:
  48. color: 'white'
  49. orientation: 'horizontal'
  50. size_hint: (0.2, 0.2)
  51. pos_hint: {"x":0.4, "top": 1}
  52. min: 10
  53. value: 20
  54. max: 150
  55. on_value_normalized: root.fontSizeSlider(self.value)
  56. MyScreenManager:
  57. mainScreen: mainScreenId
  58. MainScreen:
  59. id: mainScreenId
  60. """
  61. class DailyService(MDBoxLayout):
  62. pass
  63. class MainScreen(Screen):
  64. def __init__(self, **kwargs):
  65. super(MainScreen, self).__init__(**kwargs)
  66. def fontSizeSlider(self, value):
  67. app = MDApp.get_running_app()
  68. app.fontSize = str(int(value)) + 'dp'
  69. app.MyHeight = str( int(value) * 10 ) + 'dp'
  70. self.myRv.refresh_from_data()
  71. class MyScreenManager(ScreenManager):
  72. def __init__(self, **kwargs):
  73. super(MyScreenManager, self).__init__(**kwargs)
  74. class MyApp(MDApp):
  75. fontSize = StringProperty('20dp')
  76. MyHeight = StringProperty('200dp')
  77. def on_start(self):
  78. data = []
  79. for i in range(10):
  80. data.append({'day': 'DAY\nDAY',
  81. 'service': 'SERVICE\nSERVICE'})
  82. self.root.ids.mainScreenId.myRv.data = data
  83. def build(self):
  84. self.theme_cls.theme_style = 'Dark'
  85. self.theme_cls.primary_palette = 'Blue'
  86. self.theme_cls.accent_palette = 'Amber'
  87. return Builder.load_string(kv)
  88. if __name__ == '__main__':
  89. MyApp().run()
英文:
  1. from kivymd.app import MDApp
  2. from kivy.lang import Builder
  3. from kivy.uix.screenmanager import ScreenManager
  4. from kivy.uix.screenmanager import Screen
  5. from kivymd.uix.boxlayout import MDBoxLayout
  6. from kivy.properties import StringProperty
  7. kv = &quot;&quot;&quot;
  8. &lt;MyLabel@MDLabel&gt;:
  9. font_size: app.fontSize
  10. halign: &#39;center&#39;
  11. # Using these settings would be awesome, but cannot make it happen.
  12. # Or there might be more elegant solution?
  13. #size: self.texture_size
  14. #size_hint_y: None
  15. #text_size: self.width, None
  16. &lt;DailyService&gt;:
  17. day: &#39;&#39;
  18. service: &#39;&#39;
  19. MDGridLayout:
  20. rows: 2
  21. size_hint_y:None
  22. height:app.MyHeight
  23. MyLabel:
  24. id: firstLabelId
  25. text: root.day
  26. md_bg_color: app.theme_cls.accent_color
  27. MyLabel:
  28. id: secondLabelId
  29. md_bg_color: app.theme_cls.primary_dark
  30. text: root.service
  31. &lt;MainScreen&gt;:
  32. name: &#39;mainScreen&#39;
  33. myRv: rvId
  34. MDRelativeLayout:
  35. orientation: &#39;vertical&#39;
  36. MDRecycleView:
  37. viewclass: &#39;DailyService&#39;
  38. id: rvId
  39. rbl: rblId
  40. RecycleBoxLayout:
  41. id: rblId
  42. default_size: None, app.MyHeight
  43. default_size_hint: 1, None
  44. size_hint_y: None
  45. height: self.minimum_height
  46. orientation: &#39;vertical&#39;
  47. MDSlider:
  48. color: &#39;white&#39;
  49. orientation: &#39;horizontal&#39;
  50. size_hint: (0.2, 0.2)
  51. pos_hint: {&quot;x&quot;:0.4, &quot;top&quot;: 1}
  52. min: 10
  53. value: 20
  54. max: 150
  55. on_value_normalized: root.fontSizeSlider(self.value)
  56. MyScreenManager:
  57. mainScreen: mainScreenId
  58. MainScreen:
  59. id: mainScreenId
  60. &quot;&quot;&quot;
  61. class DailyService(MDBoxLayout):
  62. pass
  63. class MainScreen(Screen):
  64. def __init__(self, **kwargs):
  65. super(MainScreen, self).__init__(**kwargs)
  66. def fontSizeSlider(self, value):
  67. app = MDApp.get_running_app()
  68. app.fontSize = str(int(value)) + &#39;dp&#39;
  69. app.MyHeight = str( int(value) * 10 ) + &#39;dp&#39;
  70. self.myRv.refresh_from_data()
  71. class MyScreenManager(ScreenManager):
  72. def __init__(self, **kwargs):
  73. super(MyScreenManager, self).__init__(**kwargs)
  74. class MyApp(MDApp):
  75. fontSize = StringProperty(&#39;20dp&#39;)
  76. MyHeight = StringProperty(&#39;200dp&#39;)
  77. def on_start(self):
  78. data = []
  79. for i in range(10):
  80. data.append({&#39;day&#39;: &#39;DAY\nDAY&#39;,
  81. &#39;service&#39;: &#39;SERVICE\nSERVICE&#39;})
  82. self.root.ids.mainScreenId.myRv.data = data
  83. def build(self):
  84. self.theme_cls.theme_style = &#39;Dark&#39;
  85. self.theme_cls.primary_palette = &#39;Blue&#39;
  86. self.theme_cls.accent_palette = &#39;Amber&#39;
  87. return Builder.load_string(kv)
  88. if __name__ == &#39;__main__&#39;:
  89. MyApp().run()

huangapple
  • 本文由 发表于 2023年8月9日 02:28:23
  • 转载请务必保留本文链接:https://go.coder-hub.com/76862275.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定