如何根据宽高计算通知文本行数,实现GNOME扩展通知完全展开
问题核心原因与解决方案
1. Pango.Layout 计数错误的修复
你之前用Pango计算行数得到错误结果,是两个常见问题导致的:
- 未启用折行模式:默认Pango.Layout不会按宽度自动折行,
get_line_count()仅返回文本原生硬换行的数量,看起来类似单词/段落计数 - 单位不匹配:Pango的宽度单位是
Pango.Scale倍像素(默认1像素=1024 Pango单位),直接传入像素宽度会导致折行逻辑完全错误
正确的Pango行数计算代码如下:
const { Pango } = imports.gi; // 复用现有Label的字体配置,保证计算和实际渲染的字体完全一致 const fontDesc = this._expandedLabel.clutter_text.get_font_description(); const pangoLayout = this._expandedLabel.clutter_text.create_pango_layout(this._bodyText); pangoLayout.set_font_description(fontDesc); // 启用按单词+字符边界折行,和GNOME通知默认折行规则一致 pangoLayout.set_wrap(Pango.WrapMode.WORD_CHAR); // 宽度转Pango单位,同时减去左右内边距,得到文本实际可用的渲染宽度 const bodyPadding = 8; // 根据你的通知布局实际内边距调整,一般为4-8px const availableWidth = (this._bodyStack.get_width() - bodyPadding * 2) * Pango.SCALE; pangoLayout.set_width(availableWidth); const accurateLineCount = pangoLayout.get_line_count();
2. 原有宽度除法方案的偏差修复
你现在用的宽度比例计算方法存在偏差,主要是没有考虑内边距、特殊字符字宽、末尾行不足单行的问题,可按以下逻辑修正:
const singleLineWidth = this.bodyLabel.clutter_text.get_width(); const totalUnwrappedWidth = this._expandedLabel.clutter_text.get_width(); const bodyPadding = 8; // 向上取整避免末尾行被截断 const nLines = Math.ceil(totalUnwrappedWidth / (singleLineWidth - bodyPadding * 2));
3. 布局更新优化
你原来手动设置父容器高度的逻辑容易出现布局抖动,推荐用系统自带的重排方法替代,适配性更强:
this._bodyStack.layout_manager._expandLines = accurateLineCount; this._bodyStack.layout_manager.expansion = 1; // 触发层级重排,自动计算高度,不需要手动赋值 this._bodyStack.queue_relayout(); this.get_parent().queue_relayout();
自动换行行数偏高的问题说明
之前开启自动换行后行数异常偏高,基本是因为你传入的计算宽度小于文本实际可用的渲染宽度,导致折行次数变多。计算宽度时一定要扣除通知的左侧图标、右侧按钮、左右内边距的占用宽度。
内容的提问来源于stack exchange,提问作者kaanginam
相关产品推荐
相关产品推荐

