Android ImageGetter изображения с перекрытием текста - PullRequest
24 голосов
/ 24 октября 2011

Я пытаюсь загрузить блок HTML в TextView, включая изображения, используя

URLImageParser p = new URLImageParser(articleBody, this);
Spanned htmlSpan = Html.fromHtml(parsedString, p, null);

Кстати, parsedString - это HTML.Как бы то ни было, он загружается, но на изображениях нет места, чтобы их можно было разместить, поэтому они перекрывают текст над ними.Вот мой файл URLImageParser:

public class URLImageParser implements Html.ImageGetter {
Context c;
View container;

/***
 * Construct the URLImageParser which will execute AsyncTask and refresh the container
 * @param t
 * @param c
 */
public URLImageParser(View t, Context c) {
    this.c = c;
    this.container = t;
}

public Drawable getDrawable(String source) {
    URLDrawable urlDrawable = new URLDrawable();

    // get the actual source
    ImageGetterAsyncTask asyncTask = 
        new ImageGetterAsyncTask( urlDrawable);

    asyncTask.execute(source);

    // return reference to URLDrawable where I will change with actual image from
    // the src tag
    return urlDrawable;
}

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) {
        // set the correct bound according to the result from HTTP call
        Log.d("height",""+result.getIntrinsicHeight());
        Log.d("width",""+result.getIntrinsicWidth());
        urlDrawable.setBounds(0, 0, 0+result.getIntrinsicWidth(), 0+result.getIntrinsicHeight()); 

        // change the reference of the current drawable to the result
        // from the HTTP call
        urlDrawable.drawable = result;

        // redraw the image by invalidating the container
        URLImageParser.this.container.invalidate();
    }

    /***
     * Get the Drawable from URL
     * @param urlString
     * @return
     */
    public Drawable fetchDrawable(String urlString) {
        try {
            URL aURL = new URL(urlString);
            final URLConnection conn = aURL.openConnection(); 
            conn.connect(); 
            final BufferedInputStream bis = new BufferedInputStream(conn.getInputStream()); 
            final Bitmap bm = BitmapFactory.decodeStream(bis);
            Drawable drawable = new BitmapDrawable(bm);
            drawable.setBounds(0,0,bm.getWidth(),bm.getHeight());
            return drawable;
        } catch (Exception e) {
            return null;
        } 
    }
}

}

Есть идеи?Спасибо за тонну.

Ответы [ 5 ]

53 голосов
/ 18 апреля 2012

Вы можете изменить свой Cotaintainer c (view) на textView, а затем сделать свой onPostExecute следующим образом:

@Override 
protected void onPostExecute(Drawable result) { 
    // set the correct bound according to the result from HTTP call 
    Log.d("height",""+result.getIntrinsicHeight()); 
    Log.d("width",""+result.getIntrinsicWidth()); 
    urlDrawable.setBounds(0, 0, 0+result.getIntrinsicWidth(), 0+result.getIntrinsicHeight());  

    // change the reference of the current drawable to the result 
    // from the HTTP call 
    urlDrawable.drawable = result; 

    // redraw the image by invalidating the container 
    URLImageParser.this.container.invalidate();

    // For ICS
    URLImageParser.this.container.setHeight((URLImageParser.this.container.getHeight() 
    + result.getIntrinsicHeight()));

    // Pre ICS
    URLImageParser.this.textView.setEllipsize(null);
} 

Это сначала нарисует изображение, а затем сразу установит высоту TextView равной высоте рисованного элемента + высоту TextViews

2 голосов
/ 06 мая 2014

У меня недостаточно репутации, чтобы проголосовать за Мартина S, но его ответ действительно полезен. И если TextView отображал изображение по умолчанию перед загрузкой, мы можем изменить метод setHeight () следующим образом:

    URLImageParser.this.container.setHeight((URLImageParser.this.container.getHeight() 
+ result.getIntrinsicHeight()-mDefaultDrawable.getInstrinsicHeight()));
0 голосов
/ 22 августа 2015

Я нашел интересное поведение с этими решениями: если загрузка изображения происходит быстро и текстовое представление еще не было обработано (например, я использую Okhttp с кэшированием, поэтому второй вызов выполняется довольно быстро), размер текстового просмотра равен 0.

Чтобы решить эту проблему, я преобразовал ImageGetter обратно из AsyncTask и вместо этого запустил AsyncTask, который создает Spanned для моего TextView и впоследствии устанавливает текст.

С этим решением не требуется изменять размер TextView при каждой загрузке изображения.

new AsyncTask<TextView, Void, Spanned>() {
      TextView tv;
      @Override
      protected Spanned doInBackground(TextView... params) {
        tv = params[0];
        return Html.fromHtml(feedEntry.getContent(),
                new HttpImageGetter(getActivity(), HttpLoaderImpl.getInstance(getActivity())),
                new Html.TagHandler() {

                  @Override
                  public void handleTag(boolean opening, String tag, Editable output, XMLReader xmlReader) {
                    //do nothing...
                  }
                });
      }

      @Override
      protected void onPostExecute(final Spanned result) {
        new Handler(Looper.getMainLooper()).post(new Runnable() {

          @Override
          public void run() {
            tv.setText(result);
          }
        });
      }
    }.execute(textView);
0 голосов
/ 22 марта 2013

может быть, нам не нужно менять контейнер с View на TextView.

   @Override
    protected void onPostExecute(Drawable result) {
        // set the correct bound according to the result from HTTP call
        urlDrawable.setBounds(0, 0, 0 + result.getIntrinsicWidth(), 0
                + result.getIntrinsicHeight());

        // change the reference of the current drawable to the result
        // from the HTTP call
        urlDrawable.drawable = result;

        // redraw the image by invalidating the container
        URLImageParser.this.container.setMinimumHeight((URLImageParser.this.container.getHeight()+ result.getIntrinsicHeight()));
        URLImageParser.this.container.requestLayout();
        URLImageParser.this.container.invalidate();
    }
0 голосов
/ 24 октября 2011

Есть ли какая-то особая причина, по которой вам нужно загрузить его в текстовое представление?Не могли бы вы вместо этого просто использовать WebView ?

Если вы не можете использовать веб-представления, то лучшим решением будет не помещать изображения в текстовое представление.Поместите изображения в ImageView.TextViews не имеет каких-либо возможностей механизма компоновки, вам нужно выяснить, где размещать изображения и текст по отношению друг к другу.Они не являются ViewGroups (например, LinearLayout или RelativeLayout) и поэтому не имеют внутренних возможностей, определяющих компоновку.Если вы действительно не хотите использовать веб-представление (и все, что у него есть), вам нужно будет разобраться, как организовать отдельные TextViews и ImageViews самостоятельно.

...