Python/Kivy 自定义切换按钮PC端宽度对称安卓端显示异常
在KV规则中直接写width: Window.width/3属于一次性静态赋值,仅在KV文件加载时计算一次取值。PC端启动流程中窗口尺寸初始化早于KV加载,因此赋值结果符合预期;安卓端启动时,KV加载完成后才会走完屏幕适配、系统状态栏/导航栏占位计算、dpi缩放等流程,后续布局重绘时静态写入的宽度值不会同步更新,最终出现宽度被重置、显示不对称的问题。
此外使用MDRelativeLayout手动给三个按钮分别设置靠左、居中、靠右定位,搭配硬编码固定宽度的写法本身缺乏多端适配能力,不同端的控件默认内边距、父布局实际可用宽度差异都会直接导致布局错位。
推荐方案:用BoxLayout自动等分布局(零适配问题)
这是Kivy/KivyMD实现等宽并排按钮的标准写法,不需要手动计算宽度,会自动适配父布局的实际可用尺寸,PC和安卓端表现完全一致。
直接把外层的MDRelativeLayout替换为水平方向的BoxLayout,去掉按钮上硬编码的固定宽度逻辑:
BoxLayout: size_hint: 1, None height: dp(45) orientation: "horizontal" spacing: dp(2) # 可按需调整按钮之间的间距 MyButton: text: "List 1" group: "list" MyButton: text: "List 2" group: "list" MyButton: text: "List 3" group: "list"
同时修改<MyButton>对应的KV规则,删除size_hint_x: None和width: Window.width/3两行即可,BoxLayout会自动给三个子按钮均分可用宽度。
备选方案:保留RelativeLayout写法,修复静态宽度绑定问题
如果必须使用MDRelativeLayout的定位逻辑,就把静态宽度赋值改成动态绑定,确保窗口尺寸变化、布局重绘时宽度能同步更新:
首先修改MyButton类的Python代码:
from kivymd.uix.behaviors.toggle_behavior import MDToggleButton from kivymd.uix.button import MDRectangleFlatButton from kivy.core.window import Window class MyButton(MDRectangleFlatButton, MDToggleButton): def __init__(self, **kwargs): self.background_normal = (1, 1, 1, 1) super().__init__(**kwargs) self.size_hint_x = None # 绑定窗口尺寸变化事件,宽度自动更新 Window.bind(on_resize=self._update_button_width) self._update_button_width() def _update_button_width(self, *args): self.width = Window.width / 3
同步删除KV规则中<MyButton>下的size_hint_x: None和width: Window.width/3两行,避免静态赋值和动态绑定冲突。
- MDRectangleFlatButton默认带有左右内边距,如果出现按钮文字被截断、宽度被内容撑开的情况,可以在
<MyButton>的KV规则中添加padding: dp(8)(数值按需调整)适配。 - 安卓端
Window.width返回的是屏幕物理宽度,未扣除系统状态栏、底部手势导航栏的占位,手动计算宽度时容易出现偏差,优先使用父布局自动分配尺寸的写法适配性更好。
内容的提问来源于stack exchange,提问作者Hugo Cezar

