728x90
반응형
문제
- SD카드에 있는 파일을 읽어와 이미지 뷰어를 만든다. 각각 이전 그림, 다음 그림 버튼이 있으며, 버튼 사이에
'현재 그림 번호 / 전체그림 개수' 텍스트뷰가 나타나게 한다. - 토스트 메시지를 없애고, 첫 번째 그림에서 <이전 그림>을 클릭하면 마지막 그림이, 마지막 그림에서 <다음 그림>을 클릭하면 첫 번째 그림이 나오게 한다.
결과 화면
에뮬레이터 sd카드에 이미지 넣는방법은 책에 써있으니 따로 쓰지 않겠다.
XML 코드
AndroidManifest.xml
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
SD카드 접근을 위해 매니페스트에 권한을 추가해주자.
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".MainActivity">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<Button
android:id="@+id/btnPrev"
android:layout_weight="1"
android:text="이전 그림"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<TextView
android:id="@+id/textView1"
android:layout_width="80dp"
android:layout_height="wrap_content"
android:gravity="center"
android:text="1 / 5"/>
<Button
android:id="@+id/btnNext"
android:layout_weight="1"
android:text="다음 그림"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</LinearLayout>
<com.example.a1_mypictureview.MyPictureView
android:id="@+id/myPictureView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</LinearLayout>
JAVA 코드
MyPictureView.java
package com.example.a1_mypictureview;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.util.AttributeSet;
import android.view.View;
public class MyPictureView extends View {
String imagePath = null;
public MyPictureView(Context context, AttributeSet attrs){
super(context, attrs);
}
@Override
protected void onDraw(Canvas canvas){
super.onDraw(canvas);
if(imagePath != null){
Bitmap bitmap = BitmapFactory.decodeFile(imagePath);
canvas.drawBitmap(bitmap, 0, 0, null);
bitmap.recycle();
}
}
}
이미지뷰를 사용하는게 아니라 문제에서 커스텀뷰를 사용했으므로 커스텀뷰를 따로 만들어줘야한당
MainActivitiy.java
package com.example.a1_mypictureview;
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.TextView;
import android.widget.Toast;
import java.io.File;
public class MainActivity extends AppCompatActivity {
Button btnPrev, btnNext;
MyPictureView myPicture;
int curNum = 0;
File[] imageFiles;
String imageFname;
TextView textView1;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
setTitle("간단 이미지 뷰어");
ActivityCompat.requestPermissions(this, new String[] { Manifest.permission.WRITE_EXTERNAL_STORAGE}, MODE_PRIVATE);
//버튼 객체들 연결해주기
btnPrev = findViewById(R.id.btnPrev);
btnNext = findViewById(R.id.btnNext);
myPicture = findViewById(R.id.myPictureView1);
textView1 = findViewById(R.id.textView1);
//첫 화면에 처음 이미지 파일을 띄워주기 위함이다.
imageFiles = new File(Environment.getExternalStorageDirectory().getAbsolutePath() + "/Pictures").listFiles();
imageFname = imageFiles[0].toString();
myPicture.imagePath=imageFname;
//버튼에 리스너를 달아주자
btnPrev.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//첫번째 그림이라면 imgeFiles[0]이므로 curNum은 0일것이다.
//물론 초기값을 바꿔주려면 imageFiles[]의 숫자를 위에서 바꿔주면된다.
//0인상태에서 이전을 누르면 0보다 작아질것이고, 이 경우 curNum을 배열 길이-1로 바꿔준다.
//그리고 바뀐 curNum으로 imageFname에 다음 코드와 같이 적용시켜주면 끝!
if(curNum <= 0) {
curNum = imageFiles.length-1;
imageFname = imageFiles[curNum].toString();
myPicture.imagePath = imageFname;
myPicture.invalidate();
}
else {
curNum--;
imageFname = imageFiles[curNum].toString();
myPicture.imagePath = imageFname;
myPicture.invalidate();
}
textView1.setText(curNum+1 + " / " + imageFiles.length);
}
});
btnNext.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//이전 버튼과 같은 매커니즘이다.
if(curNum >= imageFiles.length-1) {
curNum = 0;
imageFname = imageFiles[curNum].toString();
myPicture.imagePath = imageFname;
myPicture.invalidate();
}
else {
curNum++;
imageFname = imageFiles[curNum].toString();
myPicture.imagePath = imageFname;
myPicture.invalidate();
}
textView1.setText(curNum+1 + " / " + imageFiles.length);
}
});
}
}
결과
추가 응용
과제로 커스텀 뷰를 사용하는 것이 아닌, 이미지뷰를 사용해서 같은 기능이 되도록 하는 것이 나왔다.
해보자!
xml코드는 커스텀 뷰 부분만 바꿔주면된다. java도 MyPictureView는 사용하지 않으므로 지워주자.
XML 코드
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<Button
android:id="@+id/btnPrev"
android:layout_weight="1"
android:text="이전 그림"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<TextView
android:id="@+id/textView1"
android:layout_width="80dp"
android:layout_height="wrap_content"
android:gravity="center"
android:textSize="20dp"/>
<Button
android:id="@+id/btnNext"
android:layout_weight="1"
android:text="다음 그림"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</LinearLayout>
<ImageView
android:id="@+id/imageView1"
android:scaleType="fitCenter"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</LinearLayout>
JAVA 코드
MainActivity.java
package com.example.homework4;
import android.Manifest;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.os.Environment;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;
import java.io.File;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
public class MainActivity extends AppCompatActivity {
Button btnPrev, btnNext;
ImageView imageView1;
int curNum = 0;
File[] imageFiles;
String imageFname;
TextView textView1;
Bitmap myBitmap;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
setTitle("이미지뷰를 이용한 이미지 뷰어");
ActivityCompat.requestPermissions(this, new String[] { Manifest.permission.WRITE_EXTERNAL_STORAGE}, MODE_PRIVATE);
//xml 객체들 연결해주기
btnPrev = findViewById(R.id.btnPrev);
btnNext = findViewById(R.id.btnNext);
imageView1 = findViewById(R.id.imageView1);
textView1 = findViewById(R.id.textView1);
//첫 화면으로 쓸 루트 지정해주기
imageFiles = new File(Environment.getExternalStorageDirectory().getAbsolutePath() + "/Pictures").listFiles();
imageFname = imageFiles[0].toString();
//기존 MyPictureView에 있던 비트맵 부분을 옮겨왔다.
//Bitmap을 이용해 현재 이미지파일 이름을 가져와주고, setImageBitmap함수를 이용해서
//첫 시작 화면 이미지뷰의 이미지를 설정해준다.
myBitmap = BitmapFactory.decodeFile(imageFname);
imageView1.setImageBitmap(myBitmap);
textView1.setText(curNum+1 + " / " + imageFiles.length);
btnPrev.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//기존 알고리즘과 비슷하고, 이미지뷰 이미지 설정만 다시 해주면된다!
if(curNum <= 0) {
curNum = imageFiles.length-1;
imageFname = imageFiles[curNum].toString();
}
else {
curNum--;
imageFname = imageFiles[curNum].toString();
}
myBitmap = BitmapFactory.decodeFile(imageFname);
imageView1.setImageBitmap(myBitmap);
textView1.setText(curNum+1 + " / " + imageFiles.length);
}
});
btnNext.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if(curNum >= imageFiles.length-1) {
curNum = 0;
imageFname = imageFiles[curNum].toString();
}
else {
curNum++;
imageFname = imageFiles[curNum].toString();
}
myBitmap = BitmapFactory.decodeFile(imageFname);
imageView1.setImageBitmap(myBitmap);
textView1.setText(curNum+1 + " / " + imageFiles.length);
}
});
}
}
결과화면은 위와 같으니 따로 붙이진 않을 것이다.
비트맵에 대한 이해가 부족해서 조금 어려웠다.
728x90
반응형
'Android, IOS > Android' 카테고리의 다른 글
[Android Sutdio를 활용한 안드로이드 프로그래밍 개정 5판] 연습문제 9장 6번 (18) | 2019.12.07 |
---|---|
[에러] all com.android.support libraries must use the exact same version specification (0) | 2019.11.30 |
[Android Sutdio를 활용한 안드로이드 프로그래밍 개정 5판] 연습문제 7-6 (0) | 2019.11.09 |
[Android Sutdio를 활용한 안드로이드 프로그래밍] 직접풀어보기 6-3 (2) | 2019.10.21 |
[에러] AAPT 에러, Android resource linking failed (0) | 2019.10.21 |