0

I have the following problem, my application retrieves data from a database online as well as the texts there are also the images I am viewing via the following class. The images are displayed correctly but not to their size, I'd like that resize based on the size of the display, you know how can I do? The source is this:

import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;

import android.graphics.BitmapFactory;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.text.Html.ImageGetter;

class HttpImageGetter implements ImageGetter {

    @Override
    public Drawable getDrawable(String source) {
            try {
                    URL url = new URL(source);
                    HttpURLConnection conn = (HttpURLConnection)url.openConnection();
                    conn.setDoInput(true);
                    conn.connect();
                    InputStream is = conn.getInputStream();
                    BitmapDrawable dr = new BitmapDrawable(BitmapFactory.decodeStream(is));
                    dr.setBounds(0, 0, dr.getIntrinsicWidth(), dr.getIntrinsicHeight());

                    return dr;
            } catch (IOException e) {
                    e.printStackTrace();
                    return null;
            }
    }
}

I also have a second problem. The opening of the text is slower as there are also images that weigh more though if I click again on the name of the text shows a screen all black and sometimes it says that the application is not responding. All this happens especially when I'm with Edge connection. Do you have ideas on how I can fix and speed up the opening of the text?

PS: The images are contained in a TextView

1 Answers1

0
private TextView htmlTextView;
private SpannableStringBuilder htmlSpannable;

@Override
public void onCreate(Bundle savedInstanceState) {

    // ...

    // first parse the html
    // replace getHtmlCode() with whatever generates/fetches your html
    Spanned spanned = Html.fromHtml(getHtmlCode());

    // we need a SpannableStringBuilder for later use
    if (spanned instanceof SpannableStringBuilder) {
        // for now Html.fromHtml() returns a SpannableStringBuiler
        // so we can just cast it
        htmlSpannable = (SpannableStringBuilder) spanned;
    } else {
        // but we have a fallback just in case this will change later
        // or a custom subclass of Html is used
        new SpannableStringBuilder(spanned);
    }

    // now we can call setText() on the next view.
    // this won't show any images yet
    htmlTextView.setText(htmlSpannable);

    // next we start a AsyncTask that loads the images
    new ImageLoadTask().execute();

    // ...

}

private class ImageLoadTask extends AsyncTask {

    DisplayMetrics metrics = new DisplayMetrics();

    @Override
    protected void onPreExecute() {

        // we need this to properly scale the images later
        getWindowManager().getDefaultDisplay().getMetrics(metrics);

    }

    @Override
    protected Void doInBackground(Void... params) {

        // iterate over all images found in the html
        for (ImageSpan img : htmlSpannable.getSpans(0,
                    htmlSpannable.length(), ImageSpan.class)) {

            if (!getImageFile(img).isFile()) {

                // here you have to download the file

            }

            // we use publishProgress to run some code on the
            // UI thread to actually show the image
            // -> onProgressUpdate()
            publishProgress(img);

        }

        return null;

    }

    @Override
    protected void onProgressUpdate(ImageSpan... values) {

        // save ImageSpan to a local variable just for convenience
        ImageSpan img = values[0];

        // now we get the File object again. so remeber to always return
        // the same file for the same ImageSpan object
        File cache = getImageFile(img);

        // if the file exists, show it
        if (cache.isFile()) {

            // first we need to get a Drawable object
            Drawable d = new BitmapDrawable(getResources(),
                    cache.getAbsolutePath());

            // next we do some scaling
            int width, height;
            int originalWidthScaled = (int) (d.getIntrinsicWidth() * metrics.density);
            int originalHeightScaled = (int) (d.getIntrinsicHeight() * metrics.density);
            if (originalWidthScaled > metrics.widthPixels) {
                height = d.getIntrinsicHeight() * metrics.widthPixels
                    / d.getIntrinsicWidth();
                width = metrics.widthPixels;
            } else {
                height = originalHeightScaled;
                width = originalWidthScaled;
            }

            // it's important to call setBounds otherwise the image will
            // have a size of 0px * 0px and won't show at all
            d.setBounds(0, 0, width, height);

            // now we create a new ImageSpan
            ImageSpan newImg = new ImageSpan(d, img.getSource());

            // find the position of the old ImageSpan
            int start = htmlSpannable.getSpanStart(img);
            int end = htmlSpannable.getSpanEnd(img);

            // remove the old ImageSpan
            htmlSpannable.removeSpan(img);

            // add the new ImageSpan
            htmlSpannable.setSpan(newImg, start, end,
                    Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);

            // finally we have to update the TextView with our
            // updates Spannable to display the image
            htmlTextView.setText(htmlSpannable);
        }
    }

    private File getImageFile(ImageSpan img) {

        // you need to implement this method yourself.
        // it must return a unique File object (or something
        // different if you also change the rest of the code)
        // for every image tag. use img.getSource() to get
        // the src="" attribute. you might want to use some
        // hash of the url as file name

    }

}

to resize image the codes included are you can change the logic as you want 20 a scaling % or whatever you want as you have the display matrics (hight and width of screen) enjoy

DisplayMetrics metrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(metrics);

int width, height;
            int originalWidthScaled = (int) (d.getIntrinsicWidth() * metrics.density);
            int originalHeightScaled = (int) (d.getIntrinsicHeight() * metrics.density);
            if (originalWidthScaled > metrics.widthPixels) {
                height = d.getIntrinsicHeight() * metrics.widthPixels
                    / d.getIntrinsicWidth();
                width = metrics.widthPixels;
            } else {
                height = originalHeightScaled;
                width = originalWidthScaled;
            }

            // it's important to call setBounds otherwise the image will
            // have a size of 0px * 0px and won't show at all
            d.setBounds(0, 0, width, height);

and loading the image in seprate thread will avoid anr

Athul Harikumar
  • 2,501
  • 18
  • 16