【问题标题】:Android Show image in TextView with SpannableStringBuilder - No errors, but no image, just plain textAndroid 在 TextView 中使用 SpannableStringBuilder 显示图像 - 没有错误,但没有图像,只是纯文本
【发布时间】:2015-09-29 11:46:44
【问题描述】:

基本上我有这样一段

导带低能级之间的差异$ec 价带$ev的上能级称为能带 差距。

现在我正在尝试解析文本,以获取那些以 $ 为前缀的符号,并将它们替换为作为数学公式的小型 PNG 图像。它们只是像 Ev 和 Ec 这样的单/dbl 字母常量符号。它们在我的资产文件夹中。基本上这是代码

public SpannableStringBuilder getConstants(String desc, String constpath){
    SpannableStringBuilder builder = new SpannableStringBuilder();
    if (desc.contains("$")){
        Matcher matcher = Pattern.compile("\\$\\w+").matcher(desc);
        int lastEnding=0;
        while (matcher.find()) {
            String constName = matcher.group();
            constName = constName.substring(1,constName.length());
            int startIndex = matcher.start();
            int endIndex = matcher.end();
            String brokenDescFirstPart = desc.substring(lastEnding, startIndex - 1);
            lastEnding = endIndex+1;
            builder.append(brokenDescFirstPart).append("   ");
            try{
                InputStream imgStream = getContext().getAssets().open(constpath+constName+".png");
                Drawable dconstImg = Drawable.createFromStream(imgStream, null);
                imgStream.close();
                builder.setSpan(new ImageSpan(dconstImg,ImageSpan.ALIGN_BOTTOM), builder.length() -3, builder.length() -1, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
                builder.append("  ");
            }catch (Exception e){
                builder.append(" ");
            }
        }
        String brokenDescLastPart = desc.substring(lastEnding, desc.length() - 1);
        builder.append(brokenDescLastPart);
    }else{
        builder = SpannableStringBuilder.valueOf(desc);
    }

    return builder;
}

代码的快速总结是 desc 是我要解析的字符串。然后我使用正则表达式获取 $word 模式并使用 matcher.match 方法遍历文本。我使用一些 int 变量来跟踪这些符号之间的起点和终点,以仔细重建嵌入图像的原始字符串。现在是代码

try{
                InputStream imgStream = getContext().getAssets().open(constpath+constName+".png");
                Drawable dconstImg = Drawable.createFromStream(imgStream, null);
                imgStream.close();
                builder.setSpan(new ImageSpan(dconstImg,ImageSpan.ALIGN_BOTTOM), builder.length() -3, builder.length() -1, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
                builder.append("  ");
            }catch (Exception e){
                builder.append(" ");
            }

是我问题的症结所在。我是从关于这个问题的其他一些问题中得到的。他们说它有效。但它不在我的范围内。我已经在整个代码中设置了断点并逐行执行。没有任何错误。还是不行。

文本在文本视图中加载了额外的空格,我有意使用这些空格来识别它必须注入图像的位置。我的 TextView 是 Android Studio 中的 Small Text View 小部件。

【问题讨论】:

  • TextUtils#dumpSpans 显示什么?也可用于测试,只需尝试 ImageSpan(Context context, int resourceId) 看看会发生什么
  • 我尝试使用该构造函数并且它有效。但问题是我想从资产文件夹加载图像。我意识到我必须在可绘制对象上调用 setBounds 并且它现在可以工作了! (它以 0x0 像素的默认大小渲染图像)我只需要弄清楚如何设置宽度和高度,以便图像与文本完美内联而不会突出。
  • getIntrinsicWidth / getIntrinsicHeight

标签: android image textview spannablestring imagespan


【解决方案1】:

我终于能够找出问题所在。事实证明,所有可绘制对象 必须 使用 setBounds() 方法进行初始化。这是我的最终代码

InputStream imgStream = getContext().getAssets().open(constpath + constName + ".png");
                Drawable dconstImg = Drawable.createFromStream(imgStream, null);
                imgStream.close();
                float aspectRatio = (float) (1.00 * dconstImg.getIntrinsicWidth() / dconstImg.getIntrinsicHeight());
                dconstImg.setBounds(0, 0, (int) Math.ceil(descTextSize * aspectRatio), (int) Math.ceil(descTextSize));
                int alignment = s ? ImageSpan.ALIGN_BOTTOM : ImageSpan.ALIGN_BASELINE;
                builder.setSpan(new ImageSpan(dconstImg,alignment), builder.length() -1, builder.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
                builder.append(" ");

descTextSize 是 TextView.getTextSize() 的结果

感谢大家帮助我解决这个问题。

【讨论】:

    【解决方案2】:

    当您可以使用 setCompundDrawblesWithIntrinsicBounds 时,为什么要跨文本?拆分段落并为其附加一个唯一的 ID。 下面的例子;

    InputStream imgStream = getContext().getAssets().open(constpath+constName+".png");
    Drawable dconstImg = Drawable.createFromStream(imgStream, null);    
    if ( Build.VERSION.SDK_INT >= 21 )
    {
        text_you_want_to_add_drawable_to.setCompoundDrawablesWithIntrinsicBounds( dconstImg, null ), null, null, null );
    } else
    {
        text_you_want_to_add_drawable_to.setCompoundDrawablesWithIntrinsicBounds( dconstImg, null, null, null );
    }
    

    【讨论】:

    • 我知道“text_you_want_to_add_drawable_to”是指一个 TextView 小部件。从文档看来,“setCompundDrawablesWithIntrinsicBounds”似乎用于在文本视图的四个侧面设置图像。但我想要的是小PNG的内联注入。就像在输入 WhatsApp 消息时使用表情符号/表情符号一样。使用 Spannable 似乎是唯一的方法。
    【解决方案3】:

    尝试关注,

    ImageSpan is = new ImageSpan(context, R.id.icon);
    text.setSpan(is, index, index + strLength, 0);
    

    在此代码中的索引 = 你的 $ 起始位置。 并且 index + strLength = 你的 $ 结束位置。

    【讨论】:

      猜你喜欢
      • 2015-02-05
      • 2017-08-15
      • 2019-12-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-04-30
      • 1970-01-01
      • 2019-06-13
      相关资源
      最近更新 更多