쪼렙 as! 풀스택

Android - HTML 형식의 TextView 에서 <img> 태그 이용하여 이미지 불러오기. 본문

개발 일지/iOS & Android

Android - HTML 형식의 TextView 에서 <img> 태그 이용하여 이미지 불러오기.

코코앱 2017. 6. 15. 17:00

안드로이드의 TextView 는 일반적으로 textSize, textColor, textStyle 같이, 서식을 한번 지정하고 사용하지만, HTML 형식을 이용하여 하나의 TextView 에서 여러형태의 문자열을 표현할 수 있다. 그러나 모든 HTML 태그를 다 사용할 수는 없고, TextView 에서 지원가능한 태그 속성들이 제한되어 있는데, 특히 이미지 태그같은 경우에는, 이미지 로더를 직접 구현해 줘야만 한다. 

  

  먼저 HTML형식의 문자열을 TextView 로 보여줄 때는, 태그가 포함된 문자열을 Spanned 객체로 만들어서 TextView 에 보여주는데, 이때 HTML 태그에서 <img> 태그를 발견하게 되면, Html.ImageGetter 인터페이스에 에 있는 getDrawable 을 호출해서 이미지를 넘겨줘야 한다. 그런데 온라인상에 있는 이미지 소스를 불러오게 되면, 바로 이미지를 넘겨줄 수 없기 때문에, AsyncTask 를 이용해서 이미지를 다운로드 받고, BitmapDrawable 로 변경시켜서 다시 반환해주도록 하는 과정을 중간에 더해줘야 한다.


  아래는 TextView 를 서브클래싱해서, Html 형식의 문자열을 TextView 에 표현해 주는 소스이다.


/**
* Created by Hyunwoo Kim (kokohapps.com), on 2017. 6. 15..
*/
public class HTMLTextView extends TextView implements Html.ImageGetter{

public HTMLTextView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
}


/**
*
* @param source HTML 형식의 문자열
*/
public void setHtmlText(String source){

Spanned spanned = Html.fromHtml(source, this, null); // Html.ImageGetter 를 여기다 구현해놨다.
this.setText(spanned);

}


/**
* Html.ImageGetter 구현.
* @param source <img> 태그의 주소가 넘어온다.
* @return 일단 LevelListDrawable 을 넘겨줘서 placeholder 처럼 보여주고, AsyncTask 를 이용해서 이미지를 다운로드
*/

@Override
public Drawable getDrawable(String source) {
LevelListDrawable d = new LevelListDrawable();

Drawable empty = ContextCompat.getDrawable(getContext(), R.mipmap.ic_launcher);
d.addLevel(0, 0, empty);
d.setBounds(0, 0, empty.getIntrinsicWidth(), empty.getIntrinsicHeight());

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

return d;
}


/**
* 실제 온라인에서 이미지를 다운로드 받을 AsyncTask
*/
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];

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;
}

/**
* 이미지 다운로드가 완료되면, 처음에 placeholder 처럼 만들어서 사용하던 Drawable 에, 다운로드 받은 이미지를 넣어준다.
*/

@Override
protected void onPostExecute(Bitmap bitmap) {

if (bitmap != null) {
BitmapDrawable d = new BitmapDrawable(getContext().getResources(), bitmap);

mDrawable.addLevel(1, 1, d);
mDrawable.setBounds(0, 0, bitmap.getWidth(), bitmap.getHeight());
mDrawable.setLevel(1);

// 이미지 다운로드 완료 후, invalidate 의 개념으로, 다시한번 텍스트를 설정해준것이다. 더 좋은방법이 있을법도 하다
CharSequence t = getText();
setText(t);
}
}
}
}




Comments