2

enter image description here

I have to show text and images exactly as TextView holds. spannable object can be used but the problem is images are being downloaded from server at run time and have to display placeholder till images are downloaded..

So I am thinking of creating Custom TextView which extends a ViewGroup but then there would be a lot of handling. let me know if there is another best option available because I have shortage of time

Naveed Ali
  • 2,609
  • 1
  • 22
  • 37
  • Can u plz give the suggestion on the same type of problem. Plz check the link https://stackoverflow.com/questions/45453202/how-to-use-the-imagestored-image-of-device-with-text-on-textview-android ...Thanks – Ravindra Kushwaha Aug 21 '17 at 06:29
  • @RavindraKushwaha check what I did to achieve above.. https://stackoverflow.com/questions/45453202/how-to-use-the-imagestored-image-of-device-with-text-on-textview-android/45913825#45913825 – Naveed Ali Aug 28 '17 at 07:37

3 Answers3

3

This can be achieved by using SpannableString and ImageSpan classes. An instance of SpannableString can be created and can be set to TeaxtView.

Instance of SpannableString can contain combination of Text and Image. Here is a quick example I could find:

public class TestActivity extends Activity { 
@Override 
public void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.main); 
            TextView textView  = (TextView) findViewById(R.id.textview); 
            SpannableString ss = new SpannableString("abc"); 
            Drawable d = getResources().getDrawable(R.drawable.icon32); 
            d.setBounds(0, 0, d.getIntrinsicWidth(), d.getIntrinsicHeight()); 
            ImageSpan span = new ImageSpan(d, ImageSpan.ALIGN_BASELINE); 
            ss.setSpan(span, 0, 3, Spannable.SPAN_INCLUSIVE_EXCLUSIVE); 
            textView.setText(ss); 
}  

Have a look at this link as well

N-JOY
  • 10,344
  • 7
  • 51
  • 69
  • I went go through this when I searched but the problem is i have to get images from server and show in the text view of recyclerView item.. the above is best in case of local images but what if there are remote images – Naveed Ali Apr 25 '16 at 08:21
  • 1
    What You can do is create a drawable instance from the Bitmap that you receive from server and then set it to ImageSpan. You will have to design that kind of architecture for lazy loading(Maybe) – N-JOY Apr 25 '16 at 08:32
  • @N-JOY Can u plz give the suggestion on the same type of problem. Plz check the link stackoverflow.com/questions/45453202/… ...Thanks – Ravindra Kushwaha Aug 21 '17 at 06:30
2

I think the easiest way to achieve this is to create a custom TextView that inside uses Html.fromHtml() to add the images and the text. You can then feed it the placeholder and when the images load you simply update with the new image. You wouldn't need to handle almost anything.

The stuff you pass to the TextView could be something of the sort:

CustomTextView(String text, List<...> plceholders)

With the text containing string placeholders for where the images should be fitted, something like "{img} test message {img}" and then a simple search and replace for {img} with the <img> tag should be enough.

You can find plenty of samples online about Html.fromHtml().

Also, N-JOY's Spannable String solution would work.

Scorpio
  • 1,124
  • 1
  • 11
  • 28
1

Here is the solution I implemented.

Spanned spanned = null;
String messageCustomized = "<img src ='"+ WebConstant.IMAGE_BASE_URL + 
part +"'/>";//WebConstant.IMAGE_BASE_URL + part;
Spanned span = Html.fromHtml(messageCustomized, new 
URLImageParser(sentMessagesViewHolder.tvMessage, context), null);
if (spanned!=null) {
    spanned = (Spanned) TextUtils.concat(spanned, span);
}else spanned= span;
if (spanned!=null) {
   txtView.setText(spanned);
}

Image Getter

public class URLImageParser implements ImageGetter {
Context context;
View container;
private int imageSize = 20;
private int imageSizeDisplaySize = 20;
URLDrawable urlDrawable = null;

public URLImageParser(View container, Context context) {
   this.context = context;
   this.container = container;
   imageSize = Utility.convertDpTopPixels(context, 20);
   imageSizeDisplaySize = Utility.convertDpTopPixels(context, 35);

}

@Override
public Drawable getDrawable(final String url) {

    String[] arr = url.split("/");
    final String fileName = arr[arr.length - 1];
    urlDrawable = new URLDrawable();
    Drawable drawable = null;
    if (Build.VERSION.SDK_INT >= 21)
        drawable = 
           context.getDrawable(R.drawable.profile_main_placeholder);
    else
        drawable = context.getResources().getDrawable(R.drawable.profile_main_placeholder);

drawable.setBounds(0, 0, 0 + imageSize, 0 + imageSize);
urlDrawable.drawable = drawable;

Bitmap bitmap = null;
bitmap = ImageUtility.getImageFromSDCard(fileName);
if (bitmap != null) {   // the bitmap is available

    bitmap = RoundedImageView.getCroppedBitmap(bitmap, imageSize, imageSize, imageSize);
    drawable = new BitmapDrawable(context.getResources(), bitmap);//ImageUtility.bitmapToDrawable(context,resource);
    drawable.setBounds(0, 0, 0 + imageSize, 0 + imageSize); //set the correct bound according to the result from HTTP call
    URLImageParser.this.urlDrawable.drawable = drawable;

} else
    Glide.with(context)
            .load(url)
            .asBitmap()
            .transform(new CircleTransform(context))
            .override(imageSizeDisplaySize, imageSizeDisplaySize)
            .into(new SimpleTarget<Bitmap>() {
                @Override
                public void onResourceReady(Bitmap resource, GlideAnimation<? super Bitmap> glideAnimation) {
                    // you can do something with loaded bitmap here
                    // .....
                    Drawable drawable = new BitmapDrawable(context.getResources(), resource);//ImageUtility.bitmapToDrawable(context,resource);
                    drawable.setBounds(0, 0, 0 + imageSize, 0 + imageSize); //set the correct bound according to the result from HTTP call
                    URLImageParser.this.urlDrawable.drawable = drawable;
                    URLImageParser.this.container.invalidate();
                    ImageUtility.saveImageToSDCard(resource, fileName);

                }
            });
return urlDrawable.drawable; //return reference to URLDrawable where We will change with actual image from the src tag
//}
}
}

Custom Bitmap Drawable

public class URLDrawable extends BitmapDrawable {
// the drawable that you need to set, you could set the initial drawing
// with the loading image if you need to
  protected Drawable drawable;

    @Override
    public void draw(Canvas canvas) {
        // override the draw to facilitate refresh function later
        if(drawable != null) {
            drawable.draw(canvas);
        }
    }
}
Naveed Ali
  • 2,609
  • 1
  • 22
  • 37