Android/6. 파일 처리

Day 113 : 간단 이미지 뷰어 만들기

pancakemaker 2022. 3. 31. 12:12

※ SD 카드 특정 폴더의 이미지 파일을 보여주는 간단한 이미지 뷰어 앱

 

- AndroidManifest.xml 설정 추가

    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

    <application
        android:requestLegacyExternalStorage="true"
        
        ...

 

- myPictureView.java (그림을 보여주는 뷰)

package com.cookandroid.project8_2;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.util.AttributeSet;
import android.view.View;

import androidx.annotation.Nullable;

public class myPictureView extends View {

    String imagePath = null;    //이미지 파일의 경로 및 파일 이름을 저장할 변수

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

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        //Bitmap 클래스는 9장에서 배울 예정
        if(imagePath != null) {
            Bitmap bitmap = BitmapFactory.decodeFile(imagePath);
            canvas.drawBitmap(bitmap, 0, 0, null);
            bitmap.recycle();
        }
    }
}

 

- 화면 디자인

<?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"
    tools:context=".MainActivity"
    android:orientation="vertical">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal">

        <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:id="@+id/btnPrev"
            android:text="이전 그림"/>

        <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:id="@+id/btnNext"
            android:text="다음 그림"/>

    </LinearLayout>

    <!-- 커스텀 위젯 - 패키지명.클래스명으로 사용 -->
    <com.cookandroid.project8_2.myPictureView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:id="@+id/myPictureView1"/>

</LinearLayout>

 

- Java 코드

package com.cookandroid.project8_2;

import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;

import android.Manifest;
import android.os.Bundle;
import android.os.Environment;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Objects;

public class MainActivity extends AppCompatActivity {
    Button btnPrev, btnNext;
    myPictureView myPicture;
    int index;         //파일의 순번으로 사용할 변수
    File[] imageFiles;
    String imageFname;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        //이 앱에 파일 액세스 작업을 허용할지 묻는 창이 나오면, <허용>을 클릭해야 함
        ActivityCompat.requestPermissions(this, new String[] {Manifest.permission.WRITE_EXTERNAL_STORAGE}, MODE_PRIVATE);
        setTitle("간단 이미지 뷰어");
        Objects.requireNonNull(getSupportActionBar()).setDisplayShowHomeEnabled(true);
        getSupportActionBar().setIcon(R.drawable.ic_launcher);

        btnPrev = (Button) findViewById(R.id.btnPrev);
        btnNext = (Button) findViewById(R.id.btnNext);
        myPicture = (myPictureView) findViewById(R.id.myPictureView1);

        imageFiles = new File(Environment.getExternalStorageDirectory().getAbsoluteFile()+"/Pictures").listFiles(); //SD카드 내 Pictures 폴더에서 파일 가져오기
        imageFname = imageFiles[index].toString(); //파일명 가져오기
        myPicture.imagePath = imageFname;           //보여지는 사진 파일 경로에 가져온 파일명 저장

        //이전 그림 클릭시
        btnPrev.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                if (index == 0) {
                    Toast.makeText(getApplicationContext(), "첫번째 그림입니다.", Toast.LENGTH_SHORT).show();
                } else {
                    index --;  //처음 그림이 아니면 cunNum 1씩 감소
                    imageFname = imageFiles[index].toString();
                    myPicture.imagePath = imageFname;
                    myPicture.invalidate(); //invalidate() -> onDraw() 호출 (9장에서 배울예정)
                }
            }
        });

        //다음 그림 클릭시
        btnNext.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                if (index >= imageFiles.length - 1) {  //배열은 0부터 시작, 길이는 1부터 시작이므로 -1 해줌
                    Toast.makeText(getApplicationContext(), "마지막 그림입니다.", Toast.LENGTH_SHORT).show();
                } else {
                    index ++;  //마지막 그림이 아니면 cunNum 1씩 증가
                    imageFname = imageFiles[index].toString();
                    myPicture.imagePath = imageFname;
                    myPicture.invalidate(); //invalidate() -> onDraw() 호출 (9장에서 배울예정)
                }
            }
        });
    }
}