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

Android三星设备Noto简体中文字体行高计算异常问题求解

三星设备Noto字体行高计算偏移问题

问题背景

我正在开发一款每行文本对应配置一个复选框的编辑器控件,近期在计算字体行高时遇到异常,问题涉及的目标字体为 NotoSansMonoCJKSC-Regular.otf。
我将该字体与consola.ttf(Consolas)字体做了对照测试,可明显观察到中文字符会逐渐下滑偏移至参考线下方。

补充场景说明:该问题仅在三星品牌手机上复现,在联想平板、小米手机上运行逻辑无异常,替换为SimHei中文字体时显示也正常。

相关测试效果截图:

  • Noto简体中文字体显示效果
  • Consolas字体显示效果

初始实现代码

OnDraw 方法实现

EditorRenderer中编写的绘制逻辑如下:

protected override void OnDraw(Canvas canvas)
{
  int height = (int)GetLineHeight(Utils.SizeUnits.px);
  int movingBaseline = Control.Baseline + CHECK_BOTTOM_MARGIN;
  int scrollY = Control.ScrollY;
  CheckBox cb;

  if (!_checks.CoordsSet)
    _checks.Init(Control.Baseline, height);

  for (int i = 0; i < _checks.Count; i++)
  {
    cb = _checks[i];
    if (!_checks.CoordsSet)
      cb.Init(movingBaseline);

    canvas.DrawRect(cb.Rect.Left, cb.Rect.Top - scrollY, cb.Rect.Right,
            cb.Rect.Bottom - scrollY, _checks.GetPaint(i));

    //font height debug
    canvas.DrawLine(cb.Rect.Left, cb.Rect.Bottom - scrollY,
                    cb.Rect.Left + Control.Width, cb.Rect.Bottom - scrollY,
                    checks.PaintCheckSolid);

    movingBaseline = Control.Baseline + CHECK_BOTTOM_MARGIN + (height * (i + 1));
  }

  _checks.CoordsSet = true;

  base.OnDraw(canvas);
}

行高计算逻辑

当前通过以下两个方法实现行高计算:

protected double GetLineHeight(SizeUnits units = SizeUnits.dp)
{

  return (CalculateLineHeight(editor, units) * _lineSpacingFactor) + 
         _lineAddedPixels;        
}

public double CalculateLineHeight(EditorEx editor, SizeUnits units)
{
    Paint.FontMetrics fm = editor.AndroidTextView.Paint.GetFontMetrics();

    return (fm.Descent - fm.Ascent) / (units == SizeUnits.px ? 1 : Resources.System.DisplayMetrics.ScaledDensity);
}

初始疑问:上述实现逻辑存在什么问题?


问题更新

我根据此前收到的答复调整了实现,尽可能使用double类型处理数值,仅在方法参数强制要求类型时才转换为int或float,调整后的OnDraw方法代码如下:

protected override void OnDraw(Canvas canvas)
{
    double height = GetLineHeight(Utils.SizeUnits.px);
    double movingBaseline = (double)Control.Baseline + CHECK_BOTTOM_MARGIN;
    double scrollY = (double)Control.ScrollY;
    CheckBox cb;

    if (!_checks.CoordsSet)
        _checks.Init(Control.Baseline, height);

    for (int i = 0; i < _checks.Count; i++)
    {
        cb = _checks[i];
        if (!_checks.CoordsSet)
            cb.Init(movingBaseline);

        canvas.DrawRect((float)cb.Rect.Left, 
                        (float)(cb.Rect.Top - scrollY), 
                        (float)cb.Rect.Right,
                        (float)(cb.Rect.Bottom - scrollY), _checks.GetPaint(i));

        //font height debug
        canvas.DrawLine((float)cb.Rect.Left,
                        (float)(cb.Rect.Bottom - scrollY),
                        (float)(cb.Rect.Left + Control.Width),
                        (float)(cb.Rect.Bottom - scrollY), _checks.PaintCheckSolid);

        movingBaseline = (double)Control.Baseline + CHECK_BOTTOM_MARGIN + (height * (double)(i + 1));
    }

    _checks.CoordsSet = true;

    base.OnDraw(canvas);

}

但调整后问题并未解决,对应异常效果有留存截图,当前疑问:是否有其他排查方向或解决方案?


内容的提问来源于stack exchange,提问作者jho

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 13:15:25