민프

[Android] 여러 페이지의 PDF 로 만들어보자(PdfDocument, Paint, Canvas, 레이아웃 캡쳐) 본문

[Android]

[Android] 여러 페이지의 PDF 로 만들어보자(PdfDocument, Paint, Canvas, 레이아웃 캡쳐)

민프야 2021. 7. 2. 17:16

현재 여행 다이어리 관련 어플을 만들고 있는데
내가 만든 여행기의 여행 루트, 사진, 메모 등을 여행 루트당 정보를 한 페이지의 PDF로 만들어 보려고 한다.

사용되는 주요 클래스로는
PdfDocument, Canvas , Paint이다.

내가 생각한 진행으로는 2가지가 있다.
1. 여행기 루트 정보 -> 레이아웃에 정보 넣기 -> 레이아웃을 Bitmap으로 캡쳐 -> Bitmap을 Canvas에 넣고 -> PDF로 생성 (계단현상 발생)

 

2. 여행기 루트 정보 -> 텍스트는 canvas.drawText, 이미지는 canvas.drawBitmap 으로 그려주기 -> PDF 생성

(Text MulitLine 문제 => StaticLayout으로 해결)

 

 

* 1번 방법에 대한 문제점:
캡쳐를 하는 것 이기 때문에
확대, 축소를 할 때 텍스트, 이미지의 계단 현상이 보이게 된다. 





따라서 Capture을 하지 말고 Pdf에 직접적으로 텍스트를 넣어 보기로 했다. 

 

 

 

* 2번 방법의 문제점:
밑 사진에서 보는 것 처럼 글자가 확대를 해도 깨지지는 않지만
Text의 Mulit라인 문제였다.
근데 이 부분은 StaticLayout으로 MutiLine 구현이 가능하다고 하니 
이 방법을 해보기로 하였다.

(StaticLayout은 처음..들어보는 것으로.. 새롭게 포스트를 써봐야겠다..)
https://minf.tistory.com/3



 

PdfDocument 

이 클래스는 네이티브 Android 콘텐츠에서 PDF 문서를 생성 할 수 있도록합니다. 새 문서를 만든 다음 추가하려는 모든 페이지에 대해 페이지를 시작하고 페이지에 콘텐츠를 작성한 다음 페이지를 완료합니다. 모든 페이지를 완료 한 후 문서를 출력 스트림에 쓰고 문서를 닫습니다. 문서를 닫은 후에는 더 이상 사용하지 마십시오. 페이지는 하나씩 작성됩니다. 즉, 주어진 시간에 작성중인 단일 페이지 만 가질 수 있습니다. 이 클래스는 스레드로부터 안전하지 않습니다.

API의 일반적인 사용은 다음과 같습니다.

 // create a new document
 PdfDocument document = new PdfDocument();

 // create a page description
 PageInfo pageInfo = new PageInfo.Builder(100, 100, 1).create();

 // start a page
 Page page = document.startPage(pageInfo);

 // draw something on the page
 View content = getContentView();
 content.draw(page.getCanvas());

 // finish the page
 document.finishPage(page);
 . . .
 // add more pages
 . . .
 // write the document content
 document.writeTo(getOutputStream());

 // close the document
 document.close();

https://developer.android.com/reference/android/graphics/pdf/PdfDocument

 

PdfDocument.PageInfo.Builder



https://developer.android.com/reference/android/graphics/pdf/PdfDocument.PageInfo.Builder


 

 

Canvas

Canvas 클래스는 "draw"호출을 보유합니다. 무언가를 그리려면 4 개의 기본 구성 요소가 필요합니다. 픽셀을 보관할 비트 맵, 드로 콜 (비트 맵에 쓰기)을 호스팅하는 캔버스, 그리기 기본 (예 : 사각형, 경로, 텍스트, 비트 맵) 및 페인트 ( 그림의 색상과 스타일을 설명하십시오).
https://developer.android.com/reference/android/graphics/Canvas

 

 

Paint

Paint 클래스에는 도형, 텍스트 및 비트 맵을 그리는 방법에 대한 스타일 및 색상 정보가 있습니다.
https://developer.android.com/reference/android/graphics/Paint

쉽게 생각해보면
Canvas는 뜻 그대로 도화지라고 생각하고 
Paint는 그 위에 그릴 수 있게 하는 것 이다.

 

       PdfDocument pdfDocument = new PdfDocument(); // Android 콘텐츠에서 PDF 문서를 생성 할 수 있도록 하는 클래스
        PdfDocument.PageInfo pageInfo = new PdfDocument.PageInfo.Builder(595,842,1).create();
        PdfDocument.Page page = pdfDocument.startPage(pageInfo);
        Canvas canvas = page.getCanvas(); // 캔버스 도화지 생성

        Paint root_image_paint = new Paint();

        pdf_root_img.buildDrawingCache();//캐쉬 저장
        Bitmap capture_bitmap = pdf_root_img.getDrawingCache();
        Bitmap resize_capture_bitmap = resizeBitmapImageFn(capture_bitmap,400);

        root_image_paint.setAntiAlias(true);
        root_image_paint.setDither(true);
        root_image_paint.setFilterBitmap(true);



        canvas.drawBitmap(resize_capture_bitmap,100,10,root_image_paint); //이미지 그려줌

        TextPaint title_paint = new TextPaint(); // 도화지 위에 그릴 수 있는 Paint클래스 선언
        String get_memo = pdf_root_text_memo.getText().toString();

        title_paint.setTextAlign(Paint.Align.CENTER); // 가운데 정렬
        title_paint.setTypeface(Typeface.create(Typeface.DEFAULT,Typeface.BOLD));
        title_paint.setTextSize(17);
//        canvas.drawText(get_memo,595/2,500,title_paint);

        StaticLayout.Builder builder = StaticLayout.Builder.obtain(get_memo
                , 0
                , get_memo.length()
                , title_paint
                , 500 );
        StaticLayout textLayout = builder.build();


        canvas.save(); // canvas의 저장
        canvas.translate(595/2,842/2+90); //canvas의 위치조정
        textLayout.draw(canvas); //레이아웃에 저장되어있는 canvas 넣어주기
        canvas.restore();
        //

        //날짜 paint
        TextPaint date_paint = new TextPaint(); // 도화지 위에 그릴 수 있는 Paint클래스 선언
        date_paint.setTextAlign(Paint.Align.CENTER);
        date_paint.setTypeface(Typeface.create(Typeface.DEFAULT,Typeface.BOLD));
        date_paint.setTextSize(17);
        canvas.drawText("2021-04-21",595/2,842/2+20,date_paint);
        //날짜 paint

        //장소 paint
        TextPaint place_paint = new TextPaint(); // 도화지 위에 그릴 수 있는 Paint클래스 선언
        place_paint.setTextAlign(Paint.Align.CENTER);
        place_paint.setTypeface(Typeface.create(Typeface.DEFAULT,Typeface.BOLD));
        place_paint.setTextSize(17);
        canvas.drawText("스코틀랜드",595/2,842/2+50,place_paint);
        //장소 paint



        pdfDocument.finishPage(page);

이런 방식으로 
여행기 정보 DB 에 있는

날짜와 장소, 장소 메모 가지고와서 넣어주면 되는 것 이다.

다음 포스트에는 이 방식으로
여행기 정보 DB에 있는 내용을 가지고 와서
여러 페이지를 담은 PDF를 만들어봐야겠다.
(다음 포스트)

https://minf.tistory.com/5

Comments