Android ImageGetter 图像重叠文本

Posted

技术标签:

【中文标题】Android ImageGetter 图像重叠文本【英文标题】:Android ImageGetter images overlapping text 【发布时间】:2011-12-13 19:03:19 【问题描述】:

我正在尝试使用

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;
         
    

有什么想法吗?非常感谢。

【问题讨论】:

您正在尝试延迟加载图像?如果是这样,我认为这只是那里的问题。为什么不尝试同时加载图像和文本? “延迟加载”到底是什么意思? 延迟加载意味着在下载图像时显示它们。另一种方法是等待图像下载,然后才显示视图。 我正在尝试做类似的事情,你能告诉我这里的 URLDrawable 是什么吗? @AbhayKumar 我认为包含 URLDrawable 的原始代码是在 ***.com/a/7442725/262462 定义的 【参考方案1】:

是否有特殊原因需要将其加载到文本视图中?你能改用WebView 吗?

如果您不能使用 Webviews,那么最好的解决方案是不要将图像放在您的文本视图中。将图像放在 ImageView 中。 TextView 没有任何布局引擎功能,您需要找出将图像和文本相互关联的位置。它们不是 ViewGroup(如 LinearLayout 或 RelativeLayout),因此没有内部布局指定功能。如果您真的不想使用 webview(以及它拥有的所有不错的布局引擎),您将不得不自己弄清楚如何安排单独的 TextView 和 ImageView。

【讨论】:

WebViews 创建不合格的体验。我正在尝试编写一个好的本机应用程序。我已经展示了我的图像,我只需要它们正确布局即可。 这是有道理的。我将过滤掉图像并单独进行。 @Nick 我认为您应该在下面选择答案。因为它正在解决textview中的问题。无需使用网络视图。 Webviews 不是为了这个目的。而且,如果在列表视图中使用 Web 视图,它们可能会出现问题。【参考方案2】:

您可以将您的硬币容器 c(视图)更改为 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 的高度设置为 drawable 的高度 + TextViews 的高度

【讨论】:

这很完美!有图像重叠的相同问题。使用此解决方案,图像可以完美显示! container.setText(container.getText()) 也可以工作(前提是容器是 TextView)。但是,我想知道强制 TextView 重做其布局的最佳方法是.. 天哪!我花了大约 6 个小时来解决这个问题,直到找到您的解决方案。我现在可以睡觉了wwww。 setHeight 不起作用 :( Eclipse 告诉使用 setMinimumHeight,但这无济于事 @Kondra007 您需要按照 Martin 的指示将 cointainer c(视图)更改为 textView,然后 eclipse 不会要求您使用 setMinimumHeight【参考方案3】:

也许我们不需要将容器从 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();
    

【讨论】:

【参考方案4】:

我没有足够的声望给 Martin S 投票,但他的回答真的很有帮助。如果 TextView 在加载前显示了默认图像,我们可以像这样更改 setHeight() 方法:

    URLImageParser.this.container.setHeight((URLImageParser.this.container.getHeight() 
+ result.getIntrinsicHeight()-mDefaultDrawable.getInstrinsicHeight()));

【讨论】:

【参考方案5】:

我发现这些解决方案的一个有趣行为: 如果图像的加载速度过快并且 textview 尚未渲染(例如,我使用带有缓存的 Okhttp,所以第二次调用非常快),则 textview 大小为 0。

为了解决这个问题,我将 ImageGetter 从 AsyncTask 转换回来,而是启动了一个 AsyncTask,它为我的 TextView 创建 Spanned 并在之后设置文本。

使用此解决方案,无需在每次加载图像时调整 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);

【讨论】:

以上是关于Android ImageGetter 图像重叠文本的主要内容,如果未能解决你的问题,请参考以下文章

Android HTML ImageGetter 作为 AsyncTask

Android - 如何显示来自可绘制资源的图像?

Android中的重叠视图

Android Canvas设置绘画时重叠部分的处理模式含效果图

网格行在Android上重叠,但在iOS上不重叠

Android EditText载入HTML内容(内容包括网络图片)