Android Показать изображение в TextView с помощью SpannableStringBuilder - нет ошибок, но нет изображения, просто текст

В основном у меня есть такой абзац

Разница между нижним энергетическим уровнем зоны проводимости $ec и верхним энергетическим уровнем валентной зоны $ev называется энергетической запрещенной зоной.

Сейчас я пытаюсь разобрать текст, получить эти символы с префиксом $ и заменить их небольшими изображениями PNG, которые являются математическими формулами. Это просто одинарные /dbl буквенно-постоянные символы, такие как Ev и Ec. Они находятся в моей папке с активами. В основном это код

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.

3 ответа

Я наконец смог разобраться в проблеме. Оказывается, что все элементы рисования ДОЛЖНЫ быть инициализированы с помощью метода 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()

Спасибо всем за ваши усилия, чтобы помочь мне разобраться с этим.

Зачем включаемый текст, когда вы можете использовать setCompundDrawblesWithIntrinsicBounds? разделите абзац и прикрепите к нему уникальный идентификатор. пример ниже;

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 );
}

Попробуйте следующее,

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

в этом кодовом индексе = ваша стартовая позиция. и index + strLength = ваша конечная позиция в $.

Другие вопросы по тегам