서론
스프링 프로젝트에서 게시판 작업으로 SUMMERNOTE를 사용한다. SUMMERNOTE는 글의 내용을 HTML로 저장하기 때문에 웹뷰가 아닌 네이티브 앱과 웹을 연동시키기 위해선 HTML을 파싱하는 작업이 필요했다.
SUMMERNOTE에서 이미지는 IMG태그로, 글은 P태그로 저장시키기 때문에 비교적 간단한 파싱으로 구현할 수 있었다.
프로젝트에서는 서버에서 HTML 소스를 받아오지만, 예시에선 HTML 소스를 하드코딩할 예정
결과 이미지는 맨 아래 있습니다~
환경설정
build.gradle 의 dependencies에 jsoup 라이브러리와 picasso 라이브러리(이미지뷰)를 추가해주세요
implementation 'org.jsoup:jsoup:1.11.3'
implementation 'com.squareup.picasso:picasso:2.71828'
코드
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".MainActivity">
<ScrollView
android:layout_width="match_parent"
android:layout_height="wrap_content">
<LinearLayout
android:gravity="center"
android:id="@+id/recipe_view_linearLayout"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content">
</LinearLayout>
</ScrollView>
</LinearLayout>
- 실제로 필요한 레이아웃은 recipe_view_linearLayout 뿐이다. (여기에 파싱해서 얻은 뷰를 자바로 넣어줄 예정)
스크롤뷰는 애교로 넣어줌
MainActivity.java
public class MainActivity extends AppCompatActivity {
private LinearLayout recipeViewLinearLayout;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
recipeViewLinearLayout = (LinearLayout) findViewById(R.id.recipe_view_linearLayout);
String htmlSource =
"<p><img src=\"/app/upload/과정1.jpg\"></p>" +
"<p>1. 준비한 채소를 한입크기로 썹니다.</p>" +
"<p>2. 채소를 볶습니다.</p>" +
"<p>3. 토마토소스와 채소육수로 간을 합니다.</p>" +
"<p><img src=\"/app/upload/과정2.jpg\"></p>" +
"<p>기호에 따라 바질이나 허브를 추가로 넣어도 좋아요!</p>";
Document doc = Jsoup.parse(htmlSource);
Elements eles = doc.getAllElements();
for (int i = 0; i < eles.size(); i++) {
if (eles.get(i).tagName().equals("img")) {
String src = getResources().getString(R.string.port) + eles.get(i).attr("src");
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
params.bottomMargin = 30;
ImageView iv = new ImageView(MainActivity.this);
Picasso.get().load(src).placeholder(R.drawable.gray).into(iv);
iv.setAdjustViewBounds(true);
iv.setMaxHeight(800);
iv.setLayoutParams(params);
recipeViewLinearLayout.addView(iv);
} else if (eles.get(i).tagName().equals("p")) {
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
params.bottomMargin = 30;
TextView tv = new TextView(MainActivity.this);
tv.setText(eles.get(i).text());
tv.setTextSize(TypedValue.COMPLEX_UNIT_SP, 14);
tv.setLayoutParams(params);
recipeViewLinearLayout.addView(tv);
}
}
}
}
Document doc = Jsoup.parse(htmlSource); -> html 소스 파싱
Elements eles = doc.getAllElements(); -> 모든 Element(태그)들 저장
eles 에 대해 for문으로 각각의 Element를 img태그인지 p태그인지 구분한다.
img 태그일 경우엔 attr("src")로 src 속성을 얻어와 서버주소를 더해 이미지를 가져온다.
ImageView를 생성해서 해당 uri를 Picasso 를 통해 해당 뷰에 넣어준다.
앞서 layout에서 만든 recipeViewLinearLayout에 뷰를 더해준다.
p 태그일 경우에는 text()로 내용을 가지고 온다.
TextView를 생성해서 뷰에 setText를 하고, 마찬가지로 레이아웃에 뷰를 추가한다.
결과
결과는 아래 사진과 같다. 왼쪽이 웹 오른쪽이 앱
웹뷰로 하면 훨씬 간단하지만, 팔로잉 등 여러 이벤트를 효과적으로 사용자에게 보이기 위해서는 네이티브 앱으로 가는게 나을 것 같다고 판단했다.
요상하게 모든 안드로이드 서비스 중 게시판이 제일 어려웠다. 웹이랑은 반대인듯.. 저만 그런가요.. 아니라고 해줘요ㅠ
'공부기록 > 안드로이드' 카테고리의 다른 글
[안드로이드] setOnKeyListener 엔터(두 번 실행되는 경우) (0) | 2021.01.28 |
---|---|
[안드로이드] Fragment to Fragment 데이터 쉽게 전달하기(자료형이 List 일 때) (0) | 2021.01.27 |
안드로이드 RecyclerView를 이용해 이미지 게시판 만들기(인스타그램 따라해보기) (0) | 2021.01.25 |
안드로이드 프래그먼트 안에 프래그먼트 - 인스타그램처럼 만들기 (0) | 2021.01.25 |
안드로이드 MaterialAlertDialog 어댑터 적용해서 팔로워 리스트 보여주기 (0) | 2021.01.25 |