안녕하세요~ 두결입니다.
지난시간에는 이미지배열을 만들고, 여러 이미지를 타이머에서 순차적으로 보여주는것을 해보았습니다.
이번시간에는 이 여러 이미지를 순차적이 아닌 랜덤으로 꺼내서 보여주는 것을 해보겠습니다.
▣ Random이란? 랜덤숫자 로그창에 출력하기
먼저, 랜덤이란것에 대해서 알아보겠습니다.
Random이란 말그대로 임의의 숫자를 생성하는 기능입니다.
흔히 난수라고 애기하는데요~
예를들면 1~10까지 중에서 아무수나 무작위로 가져오고 싶을때 사용합니다.
주사위 굴리기가 대표적인 랜덤이라고 할수있겠네요~
시간을 가지고 난수를 만들수도 있긴합니다.
예를들면 12시 24분 23.345초 라고 할때 맨뒤에 ms단위가 그때그때 바뀌기 때문에 그값으로 난수를 해도 되긴하는데
안드로이드 스튜디오에서는
Random클래스가 있기때문에 편하게 갖다쓰면 됩니다.
Random random = new Random();
int nRandom = random.nextInt(5);
위와같이 random객체를 생성하고
random.nextInt(5)함수를 사용하면 0~4까지의 값이 랜덤으로 발생되어 nRandom이라는 정수변수에 저장할수가 있습니다.
0~4가아니라 1~5중에 랜덤한 값을 얻고싶다면 +1만 해주면됩니다.
Random random = new Random();
int nRandom = random.nextInt(5)+1;
위와같이 하면 1~5사이의 랜덤값을 구할수가 있죠~
이렇게 랜덤으로 가져온 값을 타이머에서 한번 출력해보겠습니다.
public void run() {
Random random = new Random();
int nRandom = random.nextInt(15);
Log.d("랜덤숫자","값 : "+nRandom);
if(nImagePos >= 15) nImagePos = 0;
imgv_ImageTest.setImageResource(nArrImage[nImagePos++]);
}
타이머의 run()함수안에서 Random을 사용했습니다.
random.nextInt(15)라고 하였기 때문에 0~14까지의 임의의 값이 나옵니다.
그것을 Log.d()함수를 이용해서 로그창에 출력시켜보았습니다.
실행해보겠습니다.

네 위와같이 로그창에
랜덤값이 잘 나오고 있습니다.
0~14사이의 임의값이 1초마다 한번씩 출력되는것을 볼수 있습니다.
▣ 타이머에서 이미지 랜덤으로 보여주기
이제, Random값을 구했기때문에
타이머에서 이미지를 랜덤으로 보여주는 것은 쉽게 할수 있습니다.
Timer timer = new Timer();
TimerTask timerTask = new TimerTask() {
@Override
public void run() {
runOnUiThread(new Runnable() {
@Override
public void run() {
Random random = new Random();
int nRandom = random.nextInt(15);
imgv_ImageTest.setImageResource(nArrImage[nRandom]);
}
});
}
};
timer.schedule(timerTask, 1000, 1000);
ImageView의 setImageResource()로 이미지 설정할때
배열의 값을 설정하는데요~ 그 배열에서 몇번째 값을 가져올지를 랜덤값으로 설정하였습니다.
이렇게 하면 1초마다 한번씩 15개의 이미지중에 랜덤한 이미지를 보여줄 수 있습니다.
약간 짧으니까 한가지만 더해보겠습니다.
▣ 터치이벤트란?
이제부터는 터치 이벤트에대해서 한번 알아보도록 하겠습니다.
컴퓨터 프로그램에서는 마우스 클릭, 마우스 Move, 마우스 휠 등 거의 마우스로 모든 이벤트를 한다고 하면
앱프로그램에서는 마우스 대신 터치로 모든 이벤트가 이루어진다고 할수 있습니다.
동영상 재생버튼을 터치해서 실행시킨다던지
이미지를 터치한 상태로 이동해서 옮긴다던지
긴문장의 경우 터치로 스크롤한다던지..
버튼 클릭 조차도 앱프로그램에서는 터치로 이루어지죠~
그만큼 터치이벤트는 앱프로그램에서 기본이라 할수 있겠습니다.
이 터치 이벤트에도 여러가지가 있지만 대표적인것은 바로 3가지입니다.
ACTION_DOWN : 화면이나 View에 손가락을 처음 대는 순간 발생하는 이벤트입니다.
ACTION_UP : 화면이나 View에 손가락을 떼는 순간 발생하는 이벤트입니다.
ACTTION_MOVE : 화면이나 View에 손가락을 댄상태에서 움직일때 발생하는 이벤트입니다.
이 터치이벤트는 화면상에서도 적용이 되지만
특정 뷰, 그러니까 ImageView나 TextView에도 터치이벤트를 적용할수 있습니다.
예를 들면 화면상에 ImageView를 이용해서 이미지 하나를 표시했다고 할때
그 이미지를 터치했을때 무엇인가를 하고 싶을때는 ImageView의 터치이벤트를 사용하면 됩니다.
▣ ImageView의 터치이벤트 작성하기
자, 이제부터 ImageView의 터치이벤트를 한번 작성해보겠습니다.
버튼의 클릭이벤트 할때
btnTest.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
}
});
버튼의 경우에는 setOnClickListener()를 등록해서
onClick()함수에서 버튼 클릭시 할일을 작성했었는데요~
터치이벤트는
imgv_ImageTest.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View view, MotionEvent motionEvent) {
switch (motionEvent.getAction())
{
case MotionEvent.ACTION_DOWN:
// 터치했을때의 동작
break;
case MotionEvent.ACTION_UP:
// 터치를 떼었을때의 동작
break;
case MotionEvent.ACTION_MOVE:
// 터치 후 이동했을때의 동작
break;
}
return true;
}
});
위와같이 setOnTouchListener()를 등록하고
onTouch()함수안에서 할일을 작성해주면됩니다.
좀 복잡하죠? 이게 터치이벤트의 가장 기본적인 코드입니다.
버튼 클릭과 다르게 터치는 3가지 이벤트로 나누기때문에
switch()문을 이용해서
MotionEvent.ACTION_DOWN일때
MotionEvent.ACTION_UP일때
MotionEvent.ACTION_MOVE일때
각각에 대해서 할일을 정의해 주면 됩니다.
저위에 있는 코드가 복잡하고 길어보여서 저걸 언제 다 쳐야되나 싶지만 실제로
안드로이드 스튜디오에서는 탭을 누르면 코드가 자동으로 완성되는 기능이 있어서
탭 몇번만 누르면 저 코드가 완성이 되니까 걱정안하셔도 됩니다. ^^
이건 동영상으로 보여드려야 하는데 나중에 동영상으로 한번 올려드릴게요~~
자, 이제 저 터치이벤트가 잘 동작하는지 한번 코드를 넣어보겠습니다.
가장 간단한게 로그니까 로그로 출력해보겠습니다.
ImageView imgv_ImageTest = findViewById(R.id.imgvImageTest);
imgv_ImageTest.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View view, MotionEvent motionEvent) {
switch (motionEvent.getAction())
{
case MotionEvent.ACTION_DOWN:
// 터치했을때의 동작
Log.d("터치이벤트","이미지 터치 Down!!");
break;
case MotionEvent.ACTION_UP:
// 터치를 떼었을때의 동작
Log.d("터치이벤트","이미지 터치 Up!!");
break;
case MotionEvent.ACTION_MOVE:
// 터치 후 이동했을때의 동작
Log.d("터치이벤트","이미지 터치 Move!!");
break;
}
return true;
}
});
네 위와같이 3가지 이벤트에 대해서 각각 Log.d로 출력을 해보았습니다.
실행을 해보면

1초마다 15개의 이미지중에서 랜덤으로 하나씩 배열에서 꺼내서 보여주고 있습니다.
이상태에서 터치를 눌러보겠습니다.

안드로이드 스튜디오 로그창을 보면
처음에는 터치를 살짝 한뒤 바로 떼었는데
터치 Down 1회
터치 Move 2회
터치 Up 1회
가 발생하였습니다.
그다음에는 터치를 조금 길게 하고 떼었는데
터치 Down 1회
터치 Move 5회
터치 Up 1회
가 발생하였습니다.
터치를 한뒤에 딱히 이동하지도 않았지만 그 미세한 움직임을 감지해서
터치 Move이벤트도 발생한것을 알수 있습니다.
어쨌든, 터치이벤트 3가지는 잘 되네요..^^
약간 짧은 감이 있으니 마지막으로 한가지만 더해보겠습니다.
▣ 터치이벤트로 이미지 랜덤으로 보여주기 ON / OFF 하기
지금 현재는 타이머에 의해서 1초간격으로 이미지가 랜덤으로 바뀌는데요~
이 상태에서 이미지를 한번 터치하면 랜덤으로 보여주기 기능을 OFF시키고
그 상태에서 다시한번 이미지를 터치하면 랜덤으로 보여주기 기능을 ON시키는 것을 해보겠습니다.
마치 동영상의 재생/정지 버튼 같은 기능이라고 할수 있겠죠?
좀더 실감나게 하기위해서
아예 재생버튼 이미지도 만들어서 터치시에 보여주면 더 좋을것 같네요~
그럼, 먼저 재생버튼 이미지를 만들어보겠습니다.

네 위와같은 재생이미지이구요~
그림위에 표시되어야 하다보니까 빨간색 계열로 해야 잘 보일것 같네요~

play.png로 저장하였습니다.
복사해서 리소스에 붙여넣기하구요~

리소스에 잘 등록이 되었습니다.
이 play이미지를 표시할 ImageView 1개를 더 추가하겠습니다.

네 위와같이 ImgaeView를 추가해서 금방 만든 재생이미지를 설정하였습니다.
<ImageView
android:id="@+id/imgvPlay"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:srcCompat="@drawable/play"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.5" />
그리고, XML코드에서
ID는 imgvPlay라고 하였구요
위치는 화면 정가운데로 설정하였습니다.
실행을 해보면

네, 위와같이 이미지 위에 재생버튼이 잘 보이네요^^
그런데, 이 재생버튼은 터치를 했을때만 보여야 하기때문에 처음에는 안보이게 처리하겠습니다.
ImageView imgv_Play = findViewById(R.id.imgvPlay);
imgv_Play.setVisibility(View.INVISIBLE);
View를 안보이게 하는것은 setVisibility()로 할수 있습니다.
View.setVisibility()는 뷰객체의 표시상태를 제어하는 함수입니다.
View.VISIBLE은 화면에 뷰를 표시하고
View.INBIFIBLE은 화면에 뷰를 보이지않게 숨깁니다.
이렇게 처음에는 안보이게 했다가
이미지를 터치하면 보여주고 다시 터치하면 그때는 안보여주는 식으로 해주면 됩니다.
자, 그렇다면 이미지를 터치할때 마다 상태를 바뀌게 하려면 어떻게 하면 될까요?
그것은 boolean 변수 하나로 쉽게 할수 있습니다.
imgv_ImageTest.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View view, MotionEvent motionEvent) {
switch (motionEvent.getAction())
{
case MotionEvent.ACTION_DOWN:
// 터치했을때의 동작
if(bImageTouch)
{
imgv_Play.setVisibility(View.INVISIBLE);
bImageTouch = false;
}
else
{
imgv_Play.setVisibility(View.VISIBLE);
bImageTouch = true;
}
break;
case MotionEvent.ACTION_UP:
// 터치를 떼었을때의 동작
break;
case MotionEvent.ACTION_MOVE:
// 터치 후 이동했을때의 동작
break;
}
return true;
}
});
ImageView의 터치이벤트입니다.
ACTION_UP하고 ACTION_MOVE는 별도로 할일이 없으니 그냥 놔두고요
ACTION_DOWN일때, 즉 터치했을때
bImageTouch라는 값에 따라서 Play 이미지를 보여주었다 안보여주었다를 반복해주면 됩니다.
bImageTouch값 자체도 그때그때 바꾸어주고요~
자, 이제 이 bImageTouch값을 타이머에 적용하면
이미지 랜덤으로 보여주기 ON/OFF기능도 할수 있습니다.
Timer timer = new Timer();
TimerTask timerTask = new TimerTask() {
@Override
public void run() {
runOnUiThread(new Runnable() {
@Override
public void run() {
if(!bImageTouch)
{
Random random = new Random();
int nRandom = random.nextInt(15);
imgv_ImageTest.setImageResource(nArrImage[nRandom]);
}
}
});
}
};
timer.schedule(timerTask, 1000, 1000);
위와같이 타이머의 run()함수안에
if문으로 bImageTouch값이 false일때만 이미지 바뀌게 하면 됩니다.
자, 여기까지 잘 되는지 실행해보겠습니다.
https://youtube.com/shorts/D9oRZuEIpt4?si=xWMag83OFMri9T38
네 이미지가 바뀌다가도 터치를 하면 멈추고, 재생버튼이 보이고
이상태에서 다시 터치를 하면 재생버튼은 안보이고 이미지는 랜덤으로 잘 바뀌네요.^^
이번시간은 하다보니 너무 길어졌네요 ㅎㅎ
전체소스입니다. 참고하세요
MainActivity.java
package com.example.imagetest;
import android.annotation.SuppressLint;
import android.os.Bundle;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.Toast;
import androidx.activity.EdgeToEdge;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.graphics.Insets;
import androidx.core.view.ViewCompat;
import androidx.core.view.WindowInsetsCompat;
import java.util.Random;
import java.util.Timer;
import java.util.TimerTask;
public class MainActivity extends AppCompatActivity {
int nImagePos = 0;
boolean bImageTouch = false;
@SuppressLint("ClickableViewAccessibility")
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
EdgeToEdge.enable(this);
setContentView(R.layout.activity_main);
int[] nArrImage = new int[]{R.drawable.image01, R.drawable.image02,
R.drawable.image03, R.drawable.image04,
R.drawable.image05, R.drawable.image06,
R.drawable.image07, R.drawable.image08,
R.drawable.image09, R.drawable.image10,
R.drawable.image11, R.drawable.image12,
R.drawable.image13, R.drawable.image14,
R.drawable.image15};
ImageView imgv_Play = findViewById(R.id.imgvPlay);
imgv_Play.setVisibility(View.INVISIBLE);
ImageView imgv_ImageTest = findViewById(R.id.imgvImageTest);
imgv_ImageTest.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View view, MotionEvent motionEvent) {
switch (motionEvent.getAction())
{
case MotionEvent.ACTION_DOWN:
// 터치했을때의 동작
if(bImageTouch)
{
imgv_Play.setVisibility(View.INVISIBLE);
bImageTouch = false;
}
else
{
imgv_Play.setVisibility(View.VISIBLE);
bImageTouch = true;
}
break;
case MotionEvent.ACTION_UP:
// 터치를 떼었을때의 동작
break;
case MotionEvent.ACTION_MOVE:
// 터치 후 이동했을때의 동작
break;
}
return true;
}
});
Timer timer = new Timer();
TimerTask timerTask = new TimerTask() {
@Override
public void run() {
runOnUiThread(new Runnable() {
@Override
public void run() {
if(!bImageTouch)
{
Random random = new Random();
int nRandom = random.nextInt(15);
imgv_ImageTest.setImageResource(nArrImage[nRandom]);
}
}
});
}
};
timer.schedule(timerTask, 1000, 1000);
ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main), (v, insets) -> {
Insets systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars());
v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom);
return insets;
});
}
}
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 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:id="@+id/main"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<ImageView
android:id="@+id/imgvImageTest"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:srcCompat="@drawable/image01"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.5" />
<ImageView
android:id="@+id/imgvPlay"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.5"
app:srcCompat="@drawable/play" />
</androidx.constraintlayout.widget.ConstraintLayout>
자, 이번시간은 여기까지만 하도록 하구요~
다음시간부터는 대화상자와 팝업화면에 대해서 알아보도록 하겠습니다.
그럼, 이만~
감사합니다. ^^
