Load images in Html.fromHtml in textview (http url images, Base64 url images)

前端 未结 3 1183
清歌不尽
清歌不尽 2020-12-09 13:46

I have a textview in which I am showing content of a forum post, which is entered on website using rte, the content involves images, both of type web url and of type B

相关标签:
3条回答
  • 2020-12-09 14:23

    I just wanted to fix the size of the image from Rajat's answer, the image will take the full width of the textview and keeps the aspect ratio for the height. here's my update:

        public Drawable getDrawable(String source)
        {
            if(source.matches("data:image.*base64.*"))
            {
                String base_64_source = source.replaceAll("data:image.*base64", "");
                byte[] data = Base64.decode(base_64_source, Base64.DEFAULT);
                Bitmap bitmap = BitmapFactory.decodeByteArray(data, 0, data.length);
                Drawable image = new BitmapDrawable(context.getResources(), bitmap);
    
                float ratio = container.getWidth() / image.getIntrinsicWidth();
                int width = container.getWidth();
                int height = Math.round(image.getIntrinsicHeight() * ratio);
    
                image.setBounds(0, 0, width, height);
                return image;
            }
            else
            {
                ....
            }
        }
    
        public class ImageGetterAsyncTask extends AsyncTask<String, Void, Drawable>
        {
            ....
    
            @Override
            protected void onPostExecute(Drawable result)
            {
                if(result != null)
                {
                    float ratio = container.getWidth() / result.getIntrinsicWidth();
                    int width = container.getWidth();
                    int height = Math.round(result.getIntrinsicHeight() * ratio);
                    urlDrawable.setBounds(0, 0, width, height); //set the correct bound according to the result from HTTP call
                    urlDrawable.drawable = result; //change the reference of the current drawable to the result from the HTTP call
                    URLImageParser.this.container.invalidate(); //redraw the image by invalidating the container
                }
            }
    
            public Drawable fetchDrawable(String urlString)
            {
                try
                {
                    InputStream is = (InputStream) new URL(urlString).getContent();
                    Bitmap bmp = BitmapFactory.decodeStream(is);
                    Drawable drawable = new BitmapDrawable (context.getResources(), bmp);
    
                    float ratio = container.getWidth() / drawable.getIntrinsicWidth();
                    int width = container.getWidth();
                    int height = Math.round(drawable.getIntrinsicHeight() * ratio);
    
                    drawable.setBounds(0, 0, width, height);
                    return drawable;
                }
                catch (Exception e)
                {
                    return null;
                }
            }
    
        }
    }
    

    However, Ranjat's solution shows only 1 image. If you wanna show multiple images then you need to use ImageSpan inside SpannableStringBuilder if you need an example let me know in a comment.

    0 讨论(0)
  • 2020-12-09 14:28

    Finally after spending hours on this I have found the solution to the Base64 image.. I am posting the complete solution here..

    I would once again like to thank https://stackoverflow.com/a/15617341/1114536 for the base answer..

    Turns out the answer I was using as reference was just copy of this asnwer..

    URLDrawable.java

    import android.graphics.Canvas;
    import android.graphics.drawable.BitmapDrawable;
    import android.graphics.drawable.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);
            }
        }
    }
    

    URLImageParser.java

    import java.io.InputStream;
    import java.net.URL;
    
    import android.content.Context;
    import android.graphics.Bitmap;
    import android.graphics.BitmapFactory;
    import android.graphics.drawable.BitmapDrawable;
    import android.graphics.drawable.Drawable;
    import android.os.AsyncTask;
    import android.text.Html.ImageGetter;
    import android.util.Base64;
    import android.view.View;
    
    public class URLImageParser implements ImageGetter {
        Context context;
        View container;
    
        public URLImageParser(View container, Context context) {
            this.context = context;
            this.container = container;
        }
    
        public Drawable getDrawable(String source) {   
            if(source.matches("data:image.*base64.*")) {
                String base_64_source = source.replaceAll("data:image.*base64", "");
                byte[] data = Base64.decode(base_64_source, Base64.DEFAULT);
                Bitmap bitmap = BitmapFactory.decodeByteArray(data, 0, data.length);                
                Drawable image = new BitmapDrawable(context.getResources(), bitmap);
                image.setBounds(0, 0, 0 + image.getIntrinsicWidth(), 0 + image.getIntrinsicHeight()); 
                return image;
            } else {
                URLDrawable urlDrawable = new URLDrawable();
                ImageGetterAsyncTask asyncTask = new ImageGetterAsyncTask(urlDrawable);
                asyncTask.execute(source);          
                return urlDrawable; //return reference to URLDrawable where We will change with actual image from the src tag
            }        
        }
    
        public class ImageGetterAsyncTask extends AsyncTask<String, Void, Drawable> {
            URLDrawable urlDrawable;
    
            public ImageGetterAsyncTask(URLDrawable d) {
                this.urlDrawable = d;
            }
    
            @Override
            protected Drawable doInBackground(String... params) {
                String source = params[0];
                return fetchDrawable(source);
            }
    
            @Override
            protected void onPostExecute(Drawable result) {         
                urlDrawable.setBounds(0, 0, 0 + result.getIntrinsicWidth(), 0 + result.getIntrinsicHeight()); //set the correct bound according to the result from HTTP call            
                urlDrawable.drawable = result; //change the reference of the current drawable to the result from the HTTP call          
                URLImageParser.this.container.invalidate(); //redraw the image by invalidating the container
            }
    
            public Drawable fetchDrawable(String urlString) {
                try {
                    InputStream is = (InputStream) new URL(urlString).getContent();
                    Drawable drawable = Drawable.createFromStream(is, "src");
                    drawable.setBounds(0, 0, 0 + drawable.getIntrinsicWidth(), 0 + drawable.getIntrinsicHeight()); 
                    return drawable;
                } catch (Exception e) {
                    return null;
                } 
            }
        }
    }
    

    Usage:

    TextView comment_content_container = ((TextView)findViewById(R.id.comment_content));
    comment_content_container.setText(Html.fromHtml(comment.content, new URLImageParser(comment_content_container, this), null));
    

    If anyone knows better regex for the Base64, please reply I will update the answer..

    0 讨论(0)
  • 2020-12-09 14:28

    As an extra to Rajat Singhal's answer (sorry, i don't have enough reputation to post a comment):

    My drawable was having the wrong size (it was smaller), because drawables take into account the screen density. In order to preserve the original image size, I ended up doing this, in the fetchDrawable method:

    public Drawable fetchDrawable(String urlString) {
            try {
                InputStream is = (InputStream) new URL(urlString).getContent();
                Bitmap bmp = BitmapFactory.decodeStream(is);
                Drawable drawable = new BitmapDrawable (context.getResources(), bmp);
                drawable.setBounds(0, 0, drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight());
                return drawable;
            } catch (Exception e) {
                return null;
            }
        }
    
    0 讨论(0)
提交回复
热议问题