2013-03-12 3 views
55

Я искал в Google и наткнулся на этот сайт, где я нашел вопрос, похожий на мой, в котором, как включить изображение в текст TextView, например «Привет, меня зовут [image]», а также ответ был таков:Как добавить изображение в текст TextView?

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

Я хотел бы знать, в этом коде,

  1. что я должен напечатать или сделать в контексте?
  2. Я должен что-то сделать с text.setSpan() как импорт или ссылка или оставить текст?

Если кто-то может сломать это для меня, это было бы высоко оценено.

ответ

152

Попробуйте это ..

txtview.setCompoundDrawablesWithIntrinsicBounds(
        R.drawable.image, 0, 0, 0); 

Также смотрите это .. http://developer.android.com/reference/android/widget/TextView.html

Попробуйте это в XML-файле

<TextView 
     android:id="@+id/txtStatus" 
     android:layout_width="wrap_content" 
     android:layout_height="wrap_content" 
     android:layout_gravity="center" 
     android:drawableLeft="@drawable/image" 
     android:drawablePadding="5dp" 
     android:singleLine="true" 
     android:text="@string/name"/> 
+0

я получил ошибку «Не удается сделать статическую ссылку нестатический метод setCompoundDrawablesWithIntrinsicBounds (int, int, int, int) из типа TextView « – Cranosaur

+0

Спасибо Umesh, метод xml работал для меня. Я использую макет xml для своих TextViews, поэтому я не знаю, имеет ли это значение и возможно, поэтому он не работал на Java. – Cranosaur

+0

@Umesh Lakhani: Как можно поместить несколько рисунков в текст этим подходом? – Behnam

62

ком/XYZ/customandroid/TextViewWithImages.java:

import java.util.regex.Matcher; 
import java.util.regex.Pattern; 

import android.content.Context; 
import android.text.Spannable; 
import android.text.style.ImageSpan; 
import android.util.AttributeSet; 
import android.util.Log; 
import android.widget.TextView; 

public class TextViewWithImages extends TextView { 

    public TextViewWithImages(Context context, AttributeSet attrs, int defStyle) { 
     super(context, attrs, defStyle); 
    } 
    public TextViewWithImages(Context context, AttributeSet attrs) { 
     super(context, attrs); 
    } 
    public TextViewWithImages(Context context) { 
     super(context); 
    } 
    @Override 
    public void setText(CharSequence text, BufferType type) { 
     Spannable s = getTextWithImages(getContext(), text); 
     super.setText(s, BufferType.SPANNABLE); 
    } 

    private static final Spannable.Factory spannableFactory = Spannable.Factory.getInstance(); 

    private static boolean addImages(Context context, Spannable spannable) { 
     Pattern refImg = Pattern.compile("\\Q[img src=\\E([a-zA-Z0-9_]+?)\\Q/]\\E"); 
     boolean hasChanges = false; 

     Matcher matcher = refImg.matcher(spannable); 
    while (matcher.find()) { 
     boolean set = true; 
     for (ImageSpan span : spannable.getSpans(matcher.start(), matcher.end(), ImageSpan.class)) { 
      if (spannable.getSpanStart(span) >= matcher.start() 
      && spannable.getSpanEnd(span) <= matcher.end() 
       ) { 
       spannable.removeSpan(span); 
      } else { 
       set = false; 
       break; 
      } 
     } 
     String resname = spannable.subSequence(matcher.start(1), matcher.end(1)).toString().trim(); 
     int id = context.getResources().getIdentifier(resname, "drawable", context.getPackageName()); 
     if (set) { 
      hasChanges = true; 
      spannable.setSpan( new ImageSpan(context, id), 
           matcher.start(), 
           matcher.end(), 
           Spannable.SPAN_EXCLUSIVE_EXCLUSIVE 
          ); 
     } 
    } 

     return hasChanges; 
    } 
    private static Spannable getTextWithImages(Context context, CharSequence text) { 
     Spannable spannable = spannableFactory.newSpannable(text); 
     addImages(context, spannable); 
     return spannable; 
    } 
} 

Использование:

в Рез/макет/mylayout.xml:

  <com.xyz.customandroid.TextViewWithImages 
       android:layout_width="wrap_content" 
       android:layout_height="wrap_content" 
       android:textColor="#FFFFFF00" 
       android:text="@string/can_try_again" 
       android:textSize="12dip" 
       style=... 
       /> 

Обратите внимание, что если вы поместите TextViewWithImages.java в каком-то месте кроме com/xyz/customandroid/, вы также должны изменить пакет nam e, com.xyz.customandroid выше.

в Рез/значения/strings.xml:

<string name="can_try_again">Press [img src=ok16/] to accept or [img src=retry16/] to retry</string> 

где ok16.png и retry16.png иконки в Рез/рисуем/ папки

+0

Когда я использую 'textView.setText (R.string.can_try_again);' он не отображает изображения, просто показывает обычный текст 'Нажмите [img src = ok16 /], чтобы принять или [img src = retry16 /] для повтора. Любая помощь? Это потому, что я хочу динамически загружать изображения и устанавливать их в textView. –

+0

@AnasAzeem, вы можете показать ok16 и retry16 «нормально», через ImageView? Вы указали TextViewWithImages вместо TextView? – 18446744073709551615

+0

Удивительный! Спасибо! – Solata

7

Это Ответ основан на this excellent answer по 18446744073709551615. Их решение, хотя и полезно, не меняет значок изображения с окружающим текстом. Он также не устанавливает цвет значка для цвета окружающего текста.

Решение ниже принимает белый квадратный значок и позволяет соответствовать размеру и цвету окружающего текста.

public class TextViewWithImages extends TextView { 

    private static final String DRAWABLE = "drawable"; 
    /** 
    * Regex pattern that looks for embedded images of the format: [img src=imageName/] 
    */ 
    public static final String PATTERN = "\\Q[img src=\\E([a-zA-Z0-9_]+?)\\Q/]\\E"; 

    public TextViewWithImages(Context context, AttributeSet attrs, int defStyle) { 
     super(context, attrs, defStyle); 
    } 

    public TextViewWithImages(Context context, AttributeSet attrs) { 
     super(context, attrs); 
    } 

    public TextViewWithImages(Context context) { 
     super(context); 
    } 

    @Override 
    public void setText(CharSequence text, BufferType type) { 
     final Spannable spannable = getTextWithImages(getContext(), text, getLineHeight(), getCurrentTextColor()); 
     super.setText(spannable, BufferType.SPANNABLE); 
    } 

    private static Spannable getTextWithImages(Context context, CharSequence text, int lineHeight, int colour) { 
     final Spannable spannable = Spannable.Factory.getInstance().newSpannable(text); 
     addImages(context, spannable, lineHeight, colour); 
     return spannable; 
    } 

    private static boolean addImages(Context context, Spannable spannable, int lineHeight, int colour) { 
     final Pattern refImg = Pattern.compile(PATTERN); 
     boolean hasChanges = false; 

     final Matcher matcher = refImg.matcher(spannable); 
     while (matcher.find()) { 
      boolean set = true; 
      for (ImageSpan span : spannable.getSpans(matcher.start(), matcher.end(), ImageSpan.class)) { 
       if (spannable.getSpanStart(span) >= matcher.start() 
         && spannable.getSpanEnd(span) <= matcher.end()) { 
        spannable.removeSpan(span); 
       } else { 
        set = false; 
        break; 
       } 
      } 
      final String resName = spannable.subSequence(matcher.start(1), matcher.end(1)).toString().trim(); 
      final int id = context.getResources().getIdentifier(resName, DRAWABLE, context.getPackageName()); 
      if (set) { 
       hasChanges = true; 
       spannable.setSpan(makeImageSpan(context, id, lineHeight, colour), 
         matcher.start(), 
         matcher.end(), 
         Spannable.SPAN_EXCLUSIVE_EXCLUSIVE 
       ); 
      } 
     } 
     return hasChanges; 
    } 

    /** 
    * Create an ImageSpan for the given icon drawable. This also sets the image size and colour. 
    * Works best with a white, square icon because of the colouring and resizing. 
    * 
    * @param context  The Android Context. 
    * @param drawableResId A drawable resource Id. 
    * @param size   The desired size (i.e. width and height) of the image icon in pixels. 
    *      Use the lineHeight of the TextView to make the image inline with the 
    *      surrounding text. 
    * @param colour  The colour (careful: NOT a resource Id) to apply to the image. 
    * @return An ImageSpan, aligned with the bottom of the text. 
    */ 
    private static ImageSpan makeImageSpan(Context context, int drawableResId, int size, int colour) { 
     final Drawable drawable = context.getResources().getDrawable(drawableResId); 
     drawable.mutate(); 
     drawable.setColorFilter(colour, PorterDuff.Mode.MULTIPLY); 
     drawable.setBounds(0, 0, size, size); 
     return new ImageSpan(drawable, ImageSpan.ALIGN_BOTTOM); 
    } 

} 

Как использовать:

Просто вставлять ссылки на желаемые иконки в тексте. Не имеет значения, установлен ли текст программно через textView.setText(R.string.string_resource); или если он установлен в xml.

Чтобы вставить выталкиваемый значок с именем example.png, введите в текст следующую строку: [img src=example/].

Например, строка ресурса может выглядеть следующим образом:

<string name="string_resource">This [img src=example/] is an icon.</string> 
+1

Это хорошее решение. Я бы предложил только улучшение: добавьте drawable.mutate() перед drawable.setColorFilter; если вы этого не сделаете, у вас будет возможность рисования с другим цветом в других частях приложения. – moondroid

+0

@moondroid Спасибо за предложение, я отредактировал ответ соответственно. –

+0

На самом деле у меня была проблема, потому что мой drawable не является квадратным, и это решение всегда будет делать ширину выреза с той же высотой, которая будет масштабироваться пропорционально – HendraWD

3

Я перепробовал много различных решений, и это для меня было самое лучшее:

SpannableStringBuilder ssb = new SpannableStringBuilder(" Hello world!"); 
ssb.setSpan(new ImageSpan(context, R.drawable.image), 0, 1, Spannable.SPAN_INCLUSIVE_INCLUSIVE); 
tv_text.setText(ssb, TextView.BufferType.SPANNABLE); 

Этот код использует минимум памяти.

+1

. В этом случае изображение добавляется, но выравнивается с базовым текстом, который я хочу выровнять с верхней частью текста, вы можете мне помочь –

+1

он работает, но как мы можем изменить размер значка изображения в соответствии с размером текста –

0

Отчасти это основано на этом earlier answer above by @A Boschman. В этом решении я обнаружил, что размер входного изображения сильно повлиял на способность makeImageSpan() правильно выравнивать изображение по центру. Кроме того, я обнаружил, что решение повлияло на интервал между текстами, создав ненужный межстрочный интервал.

Я нашел BaseImageSpan (из библиотеки Fresco Facebook), чтобы сделать эту работу особенно хорошо:

/** 
* Create an ImageSpan for the given icon drawable. This also sets the image size. Works best 
* with a square icon because of the sizing 
* 
* @param context  The Android Context. 
* @param drawableResId A drawable resource Id. 
* @param size   The desired size (i.e. width and height) of the image icon in pixels. 
*      Use the lineHeight of the TextView to make the image inline with the 
*      surrounding text. 
* @return An ImageSpan, aligned with the bottom of the text. 
*/ 
private static BetterImageSpan makeImageSpan(Context context, int drawableResId, int size) { 
    final Drawable drawable = context.getResources().getDrawable(drawableResId); 
    drawable.mutate(); 
    drawable.setBounds(0, 0, size, size); 
    return new BetterImageSpan(drawable, BetterImageSpan.ALIGN_CENTER); 
} 

Затем поставить свой betterImageSpan экземпляр spannable.setSpan() как обычно

Смежные вопросы