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

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


Author: nxliao(xtulnx@126.com)
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 后修改。
要使用 Spannable 实现 TextView 的颜色渐变效果,你可以使用 ForegroundColorSpan 类来设置不同部分的字体颜色,并根据需要调整它们的位置和颜色值。 以下是一个示例代码,演示如何使用 Spannable 实现颜色渐变效果: ```java TextView textView = findViewById(R.id.textView); String text = "Hello World!"; Spannable spannable = new SpannableString(text); // 定义渐变色数组 int[] colors = {Color.RED, Color.GREEN, Color.BLUE}; // 定义颜色变化位置数组 float[] positions = {0f, 0.5f, 1f}; for (int i = 0; i < text.length(); i++) { // 计算当前字符的颜色 int color = interpolateColor(colors, positions, (float) i / (text.length() - 1)); // 创建 ForegroundColorSpan,并设置字体颜色 ForegroundColorSpan span = new ForegroundColorSpan(color); // 设置 span 的起始位置和结束位置 spannable.setSpan(span, i, i + 1, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); } // 将 spannable 设置给 TextView textView.setText(spannable); ``` 在这个示例中,我们首先创建了一个 SpannableString 对象,并将其初始化为需要处理的文本。然后,我们使用一个循环遍历文本中的每个字符,计算出当前字符的颜色值,然后创建一个 ForegroundColorSpan 对象,并将其应用到对应的字符上。最后,我们将处理后的 SpannableString 设置给 TextView。 在 interpolateColor 方法中,我们使用了一个插值算法来计算颜色的渐变值。你可以根据需要自定义这个方法,实现不同的颜色渐变效果。 这样,TextView 的文本就会呈现出颜色渐变的效果。你可以根据实际需求和喜好,调整渐变色数组、颜色变化位置数组以及插值算法来实现不同的颜色渐变效果。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值