Html.ImageGetter TextView

2019-01-06 15:59发布

So Im using ImageGetter to display the images from JSON blog posts. Im getting the correct source in the log but the URL changes when it reaches setBounds. Any ideas?

Code:

protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_blog_view);

    Intent intent = getIntent();
    Uri blogUri = intent.getData();
    mPost = blogUri.toString();
    mUrl = getIntent().getStringExtra("mUrl");

    TextView textView = (TextView) findViewById(R.id.scrollView1);
    textView.setText(Html.fromHtml(mPost, imgGetter, null));
}

private ImageGetter imgGetter = new ImageGetter(){
    @Override
    public Drawable getDrawable(String source){
         Drawable drawable = Drawable.createFromPath(source);
        try {
            drawable.setBounds(0, 0, drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight());
        }catch (NullPointerException e){
            logException(e);
        }
        return drawable;
    }
};

The "source" before the try is

http://www.domain.com/images_blog/feature.png

but in the catch the error is:

Unable to decode stream:

java.io.FileNotFoundException: /http:/www.domain.com/images_blog/feature.png : open failed: ENOENT (No such file or directory)

3条回答
成全新的幸福
2楼-- · 2019-01-06 16:19

This answer may help someone. I used Jsoup to extract <Img/> tag out of the string then i show the image in ImageView and <p> in Textview. Results was according to what i needed. Also i used Universal Image Loader Libaray to load images in ImageView Then i added view programmatically to the layout in my case layout was the linearlayout so i made a helper class and passed content,html string and linear layout as the parameter.

add jsoup in your project.

compile 'org.jsoup:jsoup:1.9.2'

Here some snippet.

public class PostContentHandler {
Context context;
String content;
LinearLayout linearLayout;

public PostContentHandler(Context context, String content, LinearLayout linearLayout) {
    this.context = context;
    this.content = content;
    this.linearLayout = linearLayout;

}

public void setContentToView() {

    //custom font
    Typeface bitterBoldFont = Typeface.createFromAsset(context.getAssets(), "fonts/Bitter-Regular.otf");

    List<String> p = new ArrayList<>();
    List<String> src = new ArrayList<>();
    List<String> li = new ArrayList<>();
    Document doc = Jsoup.parse(content);

    Elements elements = doc.getAllElements();

    for (Element element : elements) {
        Tag tag = element.tag();
        if (tag.getName().matches("h[1-6]{1}")) {
            String heading = element.select(tag.getName().toString()).text();
            TextView textView = new TextView(context);
            textView.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT,
                    LinearLayout.LayoutParams.WRAP_CONTENT));
            LinearLayout.LayoutParams params = (LinearLayout.LayoutParams) textView.getLayoutParams();
            int top = (int) context.getResources().getDimension(R.dimen.heading_margin_top);
            int start = (int) context.getResources().getDimension(R.dimen.content_margin);
            int end = (int) context.getResources().getDimension(R.dimen.content_margin);
            params.setMargins(start, top, end, 0);
            textView.setTextSize(20);
            textView.setTypeface(bitterBoldFont);
            textView.setText(heading);
            textView.setTextColor(context.getResources().getColor(R.color.black));
            linearLayout.addView(textView);
        }
 if (tag.getName().equalsIgnoreCase("p")) {
            element.select("img").remove();
            String body = element.html();
            TextView textView = new TextView(context);
            textView.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT,
                    LinearLayout.LayoutParams.WRAP_CONTENT));
            LinearLayout.LayoutParams params = (LinearLayout.LayoutParams) textView.getLayoutParams();
            int top = (int) context.getResources().getDimension(R.dimen.heading_margin_top);
            int start = (int) context.getResources().getDimension(R.dimen.content_margin);
            int end = (int) context.getResources().getDimension(R.dimen.content_margin);
            params.setMargins(start, top, end, 0);
            textView.setTypeface(bitterBoldFont);
            textView.setLinksClickable(true);
            textView.setAutoLinkMask(Linkify.WEB_URLS);
            textView.setText(Html.fromHtml(body));
            textView.setTextColor(context.getResources().getColor(R.color.content_color));
            linearLayout.addView(textView);
            p.add(body);
        }
        if (tag.getName().equalsIgnoreCase("ol")) {
            String ol = element.select(tag.getName().toString()).outerHtml();
            TextView textView = new TextView(context);
            textView.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT,
                    LinearLayout.LayoutParams.WRAP_CONTENT));
            LinearLayout.LayoutParams params = (LinearLayout.LayoutParams) textView.getLayoutParams();
            params.setMarginStart((int) context.getResources().getDimension(R.dimen.content_margin));
            int top = (int) context.getResources().getDimension(R.dimen.heading_margin_top);
            int start = (int) context.getResources().getDimension(R.dimen.content_margin);
            int end = (int) context.getResources().getDimension(R.dimen.content_margin);
            params.setMargins(start, top, end, 0);
            textView.setTypeface(bitterBoldFont);
            textView.setLinksClickable(true);
            textView.setAutoLinkMask(Linkify.WEB_URLS);
            textView.setTextColor(context.getResources().getColor(R.color.content_color));
            textView.setText(Html.fromHtml(ol, null, new MyTagHandler()));
            linearLayout.addView(textView);

        }
        if (tag.getName().equalsIgnoreCase("ul")) {
            String ul = element.select(tag.getName().toString()).outerHtml();
            TextView textView = new TextView(context);

            textView.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT,
                    LinearLayout.LayoutParams.WRAP_CONTENT));
            LinearLayout.LayoutParams params = (LinearLayout.LayoutParams) textView.getLayoutParams();
            int top = (int) context.getResources().getDimension(R.dimen.heading_margin_top);
            int start = (int) context.getResources().getDimension(R.dimen.content_margin);
            int end = (int) context.getResources().getDimension(R.dimen.content_margin);
            params.setMargins(start, top, end, 0);
            textView.setTypeface(bitterBoldFont);
            textView.setLinksClickable(true);
            textView.setAutoLinkMask(Linkify.WEB_URLS);
            textView.setTextColor(context.getResources().getColor(R.color.content_color));
            textView.setText(Html.fromHtml(ul, null, new MyTagHandler()));
            linearLayout.addView(textView);
        }
        if (tag.getName().equalsIgnoreCase("img")) {
            String url = element.select("img").attr("src");
            final ImageView imageView = new ImageView(context);
            imageView.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT,
                    LinearLayout.LayoutParams.WRAP_CONTENT));
            final ProgressBar progressBar = new ProgressBar(context);
            linearLayout.addView(progressBar);
            progressBar.setVisibility(View.GONE);
            ImageLoader imageLoader = ImageLoader.getInstance();
            imageLoader.displayImage(url, imageView, new SimpleImageLoadingListener() {
                @Override
                public void onLoadingComplete(String imageUri, View view, Bitmap loadedImage) {
                    super.onLoadingComplete(imageUri, view, loadedImage);
                    progressBar.setVisibility(View.INVISIBLE);
                    int height = loadedImage.getHeight();
                    imageView.getLayoutParams().height = getScreenWidth();
                    imageView.setAdjustViewBounds(true);
                    imageView.requestLayout();
                }

                @Override
                public void onLoadingStarted(String imageUri, View view) {
                    super.onLoadingStarted(imageUri, view);
                    progressBar.setVisibility(View.VISIBLE);
                }
            });
            linearLayout.addView(imageView);
            src.add(url);
        }

    }
}

public static int getScreenWidth() {
    return Resources.getSystem().getDisplayMetrics().widthPixels;
}
}

I hope my answer will help someone.

查看更多
The star\"
3楼-- · 2019-01-06 16:22

If you have mTV (I mean TextView), you can calculate based on its dimensions (mTv.getWidth() and mTv.getHeight()) and dimension of created bitmap (bitmap.getWidth() and bitmap.getHeight()) and set these values as new dimensions of TextView (mTv).

        if (bitmap != null) {
            BitmapDrawable d = new BitmapDrawable(bitmap);
            mDrawable.addLevel(1, 1, d);
            int width = mTv.getWidth() < bitmap.getWidth() ? mTv.getWidth() : bitmap.getWidth();
            int height = bitmap.getHeight() * width / bitmap.getWidth();
            mDrawable.setBounds(0, 0, width, height);
            mDrawable.setLevel(1);
            // i don't know yet a better way to refresh TextView 
            // mTv.invalidate() doesn't work as expected 
            // but we can calculate new TextView dimensions
            mTv.setHeight(height);
            CharSequence t = mTv.getText();
            mTv.setText(t);
        } 
查看更多
我只想做你的唯一
4楼-- · 2019-01-06 16:39

the easiest solution is:

import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;

import org.pskink.soom.R;

import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.LevelListDrawable;
import android.os.AsyncTask;
import android.os.Bundle;
import android.text.Html;
import android.text.Html.ImageGetter;
import android.text.Spanned;
import android.util.Log;
import android.widget.TextView;

public class TestImageGetter extends Activity implements ImageGetter {
    private final static String TAG = "TestImageGetter";
    private TextView mTv;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.test_image_getter);
        String source = "this is a test of <b>ImageGetter</b> it contains " +
                "two images: <br/>" +
                "<img src=\"http://developer.android.com/assets/images/dac_logo.png\"><br/>and<br/>" +
                "<img src=\"http://developer.android.com/assets/images/icon_search.png\">";

        Spanned spanned = Html.fromHtml(source, this, null);
        mTv = (TextView) findViewById(R.id.text);
        mTv.setText(spanned);
    }

    @Override
    public Drawable getDrawable(String source) {
        LevelListDrawable d = new LevelListDrawable();
        Drawable empty = getResources().getDrawable(R.drawable.ic_launcher);
        d.addLevel(0, 0, empty);
        d.setBounds(0, 0, empty.getIntrinsicWidth(), empty.getIntrinsicHeight());

        new LoadImage().execute(source, d);

        return d;
    }

    class LoadImage extends AsyncTask<Object, Void, Bitmap> {

        private LevelListDrawable mDrawable;

        @Override
        protected Bitmap doInBackground(Object... params) {
            String source = (String) params[0];
            mDrawable = (LevelListDrawable) params[1];
            Log.d(TAG, "doInBackground " + source);
            try {
                InputStream is = new URL(source).openStream();
                return BitmapFactory.decodeStream(is);
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            } catch (MalformedURLException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
            return null;
        }

        @Override
        protected void onPostExecute(Bitmap bitmap) {
            Log.d(TAG, "onPostExecute drawable " + mDrawable);
            Log.d(TAG, "onPostExecute bitmap " + bitmap);
            if (bitmap != null) {
                BitmapDrawable d = new BitmapDrawable(bitmap);
                mDrawable.addLevel(1, 1, d);
                mDrawable.setBounds(0, 0, bitmap.getWidth(), bitmap.getHeight());
                mDrawable.setLevel(1);
                // i don't know yet a better way to refresh TextView
                // mTv.invalidate() doesn't work as expected
                CharSequence t = mTv.getText();
                mTv.setText(t);
            }
        }
    }
}

there is one not quite elegant way to re-layout a TextView after image downloading:

// i don't know yet a better way to refresh TextView
// mTv.invalidate() doesn't work as expected
CharSequence t = mTv.getText();
mTv.setText(t);

if anybody knows better solution please let me know

查看更多
登录 后发表回答