分析 TextView 应用 Spannable 风格后 ellipsize 属性失效

分析 TextView 应用 Spannable 风格后 ellipsize 属性失效


Author: nxliao([email protected])
Date:   2013-05-20

环境:

为使 TextView 在超小号字体情况下不因 descent 导致纯中文和纯英文显示不在同一水平线,使用 spannable 风格:

favorite.setText(info.getTitle(),TextView.BufferType.SPANNABLE);

参考:

http://stackoverflow.com/questions/14691511/textview-using-spannable-ellipsize-doesnt-work

问题:

使用 spannable 后,无法应用 android:ellipsize 属性。

分析:

  1. TextView.makeSingleLayout 构造 DynamicLayout 做为 mLayout;

  2. DynamicLayout.reflow 调用 StaticLayout.generate 解析文字布局;

  3. 通过 reflowed 获取 省略(ellipsis)内容:

        if (mEllipsize) {
            ints[ELLIPSIS_START] = reflowed.getEllipsisStart(i);
            ints[ELLIPSIS_COUNT] = reflowed.getEllipsisCount(i);
        }
        mInts.insertAt(startline + i, ints);
    
  4. 经调试(在 TextView.draw 断点),修改 ((DynamicLayout)((TextView)v).mLayout) 之 mInts.mValues 的 [3]及[4],会响应到 mLayout.mText,而 mLayout.mText 即显示出来的内容。

    因此,问题应该出在第2步的结果。从数值均为0来看,可能是没有调用: StaticLayout.calculateEllipsis


StaticLayout.out

        boolean doEllipsis =
                    (((mMaximumVisibleLineCount == 1 && moreChars) || (firstLine && !moreChars)) &&
                            ellipsize != TextUtils.TruncateAt.MARQUEE) ||
                    (!firstLine && (currentLineIsTheLastVisibleOne || !moreChars) &&
                            ellipsize == TextUtils.TruncateAt.END);

原因:

DynamicLayout.reflow 

    synchronized (sLock) {
        reflowed = sStaticLayout;
        sStaticLayout = null;
    }

    if (reflowed == null) {
        reflowed = new StaticLayout(null);
    } else {
        reflowed.prepare();
    }

默认构造中, StaticLayout.mMaximumVisibleLineCount = Integer.MAX_VALUE;

修改:

  1. 通过反射,修改 DynamicLayout.sStaticLayout.mMaximumVisibleLineCount = 1 即可。
  2. 这是一静态变量,改一次即可。
  3. 时机可选为 TextView.draw,试取 getLayout() 判断,或是预先构造 DynamicLayout 模拟计算,待创建静态成员 sStaticLayout 后修改。

你可能感兴趣的:(程序,android)