Lotto 생성 앱 만들기
Splash 화면
- Activity로 생성
- Lottie Animation 사용: 원하는 화면을 json 형태로 다운
- Raw 폴더 생성 후, 위에서 다운 받은 이미지를 복사해서 넣기
- Resource 안에 있는 모든 리소스들은 반드시 영소문자로 시작하고, 이들로 구성되며, 특수문자는 _ 만 가능
Lottie animation
- Splash 화면에 애니메이션 사용하려면 Lottie animation play라는 library가 필요
- Lottie Files 사이트에서 open source가 저장되어 있는 Repository로 이동하여, “Lottie Android” 클릭
- airbnb site에 들어가서 dependency 추가 –> Module 단위의 Gradle에 추가 (버전 수정) –> sync now
Splash_Layout
LottieAnimationView 포함시키고 여러가지 설정
- centerCrop: 비율은 유지한 채, 화면 전체를 가득 채우도록 함
- loop option true: 반복 play
- Autoplay option true: 자동으로 애니매이션 시작
아래는 전체 소스코드이다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<?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:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".SplashActivity">
<com.airbnb.lottie.LottieAnimationView
android:id="@+id/animationView"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:lottie_rawRes="@raw/winners_animation"
android:scaleType="centerCrop"
app:lottie_loop="true"
app:lottie_autoPlay="true"/>
</androidx.constraintlayout.widget.ConstraintLayout>
Manifest
- 앱 실행 시, 제일 먼저 실행되기 위해서 manifest 파일에서 MainActivity에 있던 intent-filter를 splashacitivity로 이동
- Splash 화면의 액션 바를 삭제하기 위해서 Activity theme를 no action bar 로 바꾼다. (Main Activity도 동일하게 적용)
- 실행: Lottie에서 다운 받은 애니메이션이 Splash로 나타남을 확인
SplashActivity
- Splash 화면을 터치하면 MainActivity로 넘어가도록 설정
- 앞서 정한 animationView에 onClickListener 적용
- intent를 MainActivity로 설정
- Splash 화면을 터치하지 않아도 일정시간(3초)이 지나면 MainActivity로 넘어가도록 설정
- Handler 클래스의 postDelayed 사용: 일정시간 후에 특정한 코드 블럭을 실행할 수 있도록 하는 메소드
- Runnable interface를 구현한 코드 블럭과 지연시간을 parameter로 넘겨줘야 한다.
- 지연시간 후에 runnable 실행
- 생성자 Handler()는 deprecated 되었으므로 parameter로 이 runnable이 실행될 쓰레드를 넘겨준다.
- Looper.getMainLooper(): 메인 쓰레드와 연관된 looper를 가져와서 메인 쓰레드에 runnable 객체를 붙여준다.
- Handler 클래스의 postDelayed 사용: 일정시간 후에 특정한 코드 블럭을 실행할 수 있도록 하는 메소드
- 1,2 실행 결과: splash 화면을 클릭하면 메인 화면이 2번 나오게 된다. (onClickListener의 intent, Handler의 intent가 둘 다 실행되는 문제)
- click을 통해서 mainactivity로 이동할 때는 Handler에 붙어있는 callback을 제거해야 한다.
- onClickListener 내부에 removeCallbacks(Runnable) 함수 호출
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
import android.os.Bundle
import android.os.Handler
import android.os.Looper
import android.view.View
import com.airbnb.lottie.Lottie
import com.airbnb.lottie.LottieAnimationView
class SplashActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_splash)
val animationView : LottieAnimationView = findViewById(R.id.animationView)
val handler = Handler(Looper.getMainLooper())
val runnable = Runnable {
val intent = Intent(this, MainActivity::class.java)
startActivity(intent)
finish()
}
handler.postDelayed(runnable, 3000)
animationView.setOnClickListener {
handler.removeCallbacks(runnable)
val intent = Intent(this, MainActivity::class.java)
startActivity(intent)
finish()
}
}
}
Main 화면
Main_Layout
- 아래와 같이 구성
- Lotto 숫자 표시를 위해 TextView를 6개 만들고, 배경은 커스터마이징한 원 이용
- Res 폴더의 drawable에서 오른쪽 마우스를 클릭하여 new - Drawable Resource File 클릭 후 이름 지정하여 생성
- shape 지정: oval
- 속성 지정: stroke(두께), solid(원 내부 )
- 색상: Resource manager를 이용하여 직접 생성
1
2
3
4
5
6
7
8
9
10
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<shape android:shape="oval">
<stroke android:width="4dp" android:color="@color/ballStroke"/>
<solid android:color="@color/ballSolid"/>
</shape>
</item>
</selector>
아래와 같이 만들어진다.
- 가장 밑에 있는 원판은 animation이 자동으로 실행되지 않도록, 또 반복 실행되지 않도록 splash와 다르게 loop, autoPlay option을 false로 지정
전체 소스 코드는 아래와 같다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
<?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:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<com.airbnb.lottie.LottieAnimationView
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_constraintTop_toTopOf="parent"
app:lottie_rawRes="@raw/money"
android:scaleType="fitStart"
app:lottie_loop="true"
app:lottie_autoPlay="true"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
android:orientation="horizontal"
android:gravity="center_horizontal">
<TextView
android:id="@+id/number1"
android:layout_width="50dp"
android:layout_height="50dp"
android:layout_marginHorizontal="4dp"
android:text="7"
android:textSize="24sp"
android:textStyle="bold"
android:gravity="center"
android:background="@drawable/lottery_ball"/>
<TextView
android:id="@+id/number2"
android:layout_width="50dp"
android:layout_height="50dp"
android:layout_marginHorizontal="4dp"
android:text="7"
android:textSize="24sp"
android:textStyle="bold"
android:gravity="center"
android:background="@drawable/lottery_ball"/>
<TextView
android:id="@+id/number3"
android:layout_width="50dp"
android:layout_height="50dp"
android:layout_marginHorizontal="4dp"
android:text="7"
android:textSize="24sp"
android:textStyle="bold"
android:gravity="center"
android:background="@drawable/lottery_ball"/>
<TextView
android:id="@+id/number4"
android:layout_width="50dp"
android:layout_height="50dp"
android:layout_marginHorizontal="4dp"
android:text="7"
android:textSize="24sp"
android:textStyle="bold"
android:gravity="center"
android:background="@drawable/lottery_ball"/>
<TextView
android:id="@+id/number5"
android:layout_width="50dp"
android:layout_height="50dp"
android:layout_marginHorizontal="4dp"
android:text="7"
android:textSize="24sp"
android:textStyle="bold"
android:gravity="center"
android:background="@drawable/lottery_ball"/>
<TextView
android:id="@+id/number6"
android:layout_width="50dp"
android:layout_height="50dp"
android:layout_marginHorizontal="4dp"
android:text="7"
android:textSize="24sp"
android:textStyle="bold"
android:gravity="center"
android:background="@drawable/lottery_ball"/>
</LinearLayout>
<com.airbnb.lottie.LottieAnimationView
android:id="@+id/lotteryButton"
android:layout_width="300dp"
android:layout_height="200dp"
app:lottie_rawRes="@raw/lottery"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:lottie_loop="false"
app:lottie_autoPlay="false"/>
</androidx.constraintlayout.widget.ConstraintLayout>
MainActivity
- 원판을 클릭하면 애니메이션이 실행되되록 설정
- isAnimating이 false 이면 원판을 playAnimation()을 통해 애니메이션을 실행
- 원판이 돌고 있을 때 클릭하면 애니메이션 정지
- isAnimating이 true 이면 원판을 cancelAnimation()을 통해 애니메이션 정지
- 원판이 계속 돌고 있는 동안 랜덤숫자를 계속해서 발생시켜 숫자가 바뀌도록 설정
- timer 사용
- CountDownTimer 는 abstract 클래스로 바로 사용할 수는 없고 상속받거나 익명 클래스로 객체 생성 (여기서는 익명 클래스)
- forEach문을 통해, 로또 번호 6개 각각에 대하여 랜덤넘버를 생성
- forEach문을 통해, 로또 번호 6개 각각에 대하여 랜덤넘버를 생성
전체 소스코드는 아래와 같다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
package com.example.myapplication
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.os.CountDownTimer
import android.widget.TextView
import com.airbnb.lottie.LottieAnimationView
import org.w3c.dom.Text
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val lotteryButton : LottieAnimationView = findViewById(R.id.lotteryButton)
val number1 : TextView = findViewById(R.id.number1)
val number2 : TextView = findViewById(R.id.number2)
val number3 : TextView = findViewById(R.id.number3)
val number4 : TextView = findViewById(R.id.number4)
val number5 : TextView = findViewById(R.id.number5)
val number6 : TextView = findViewById(R.id.number6)
val lotteryNumbers = arrayListOf(number1, number2, number3, number4, number5, number6)
val countDownTimer = object: CountDownTimer(3000, 100){
override fun onFinish() {
}
override fun onTick(millisUntilFinished: Long) {
lotteryNumbers.forEach{
val randomNumber = (Math.random() * 45 + 1).toInt() //1~45
it.text = "$randomNumber" // number 각각 개별 객체 it
}
}
}
lotteryButton.setOnClickListener{
if(lotteryButton.isAnimating){
lotteryButton.cancelAnimation()
countDownTimer.cancel()
}
else{
lotteryButton.playAnimation()
countDownTimer.start()
}
}
}
}
실행결과
실행 결과는 아래와 같다.
전체 소스코드 https://github.com/eunhwa99/android_project/tree/master/lotto
참고자료
유튜브 - 슬기로운 코딩 생활