Изображения изображений с изображениями Android ImageGetter
Я пытаюсь загрузить блок 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;
}
}
}
}
Любые идеи? Спасибо тонну.
Ответы
Ответ 1
Есть ли конкретная причина, по которой вам нужно загрузить его в текстовое представление? Не могли бы вы вместо этого использовать WebView?
Если вы не можете использовать Webviews, лучшее решение - не помещать изображения в текстовое представление. Поместите изображения в ImageView. TextViews не имеют каких-либо возможностей механизма компоновки, которые вам нужны, чтобы выяснить, где размещать изображения и тексты по отношению друг к другу. Они не являются ViewGroups (например, LinearLayout или RelativeLayout) и, следовательно, не имеют внутренних возможностей определения макета. Если вы действительно не хотите использовать веб-просмотр (и все, что у него есть), вам нужно будет выяснить, как организовать отдельные объекты TextViews и ImageViews самостоятельно.
Ответ 2
Вы можете изменить свой cointainer 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
Ответ 3
У меня недостаточно репутации, чтобы проголосовать за Martin S, но его ответ действительно полезен. И если TextView отобразил изображение по умолчанию перед загрузкой, мы можем изменить метод setHeight() следующим образом:
URLImageParser.this.container.setHeight((URLImageParser.this.container.getHeight()
+ result.getIntrinsicHeight()-mDefaultDrawable.getInstrinsicHeight()));
Ответ 4
может быть не нужно менять контейнер из 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();
}
Ответ 5
Я нашел интересное поведение с этими решениями:
если загрузка изображения выполняется быстро, и текстовое изображение еще не было отображено (например, я использую 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);