You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何根据宽高计算通知文本行数,实现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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.07 15:48:04