Home Lotto Generator App
Post
Cancel

Lotto Generator App

Lotto 생성 앱 만들기

Splash 화면

  1. Activity로 생성
  2. Lottie Animation 사용: 원하는 화면을 json 형태로 다운
  3. Raw 폴더 생성 후, 위에서 다운 받은 이미지를 복사해서 넣기
    • Resource 안에 있는 모든 리소스들은 반드시 영소문자로 시작하고, 이들로 구성되며, 특수문자는 _ 만 가능

Lottie animation

사이트: https://lottiefiles.com/

  • 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

  1. Splash 화면을 터치하면 MainActivity로 넘어가도록 설정
    • 앞서 정한 animationView에 onClickListener 적용
    • intent를 MainActivity로 설정
  2. Splash 화면을 터치하지 않아도 일정시간(3초)이 지나면 MainActivity로 넘어가도록 설정
    • Handler 클래스의 postDelayed 사용: 일정시간 후에 특정한 코드 블럭을 실행할 수 있도록 하는 메소드
      • Runnable interface를 구현한 코드 블럭과 지연시간을 parameter로 넘겨줘야 한다.
      • 지연시간 후에 runnable 실행
    • 생성자 Handler()는 deprecated 되었으므로 parameter로 이 runnable이 실행될 쓰레드를 넘겨준다.
      • Looper.getMainLooper(): 메인 쓰레드와 연관된 looper를 가져와서 메인 쓰레드에 runnable 객체를 붙여준다.
  3. 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

  • 아래와 같이 구성

  1. 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>

아래와 같이 만들어진다.

  1. 가장 밑에 있는 원판은 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

  1. 원판을 클릭하면 애니메이션이 실행되되록 설정
    • isAnimating이 false 이면 원판을 playAnimation()을 통해 애니메이션을 실행
  2. 원판이 돌고 있을 때 클릭하면 애니메이션 정지
    • isAnimating이 true 이면 원판을 cancelAnimation()을 통해 애니메이션 정지
  3. 원판이 계속 돌고 있는 동안 랜덤숫자를 계속해서 발생시켜 숫자가 바뀌도록 설정
    • timer 사용
    • CountDownTimer 는 abstract 클래스로 바로 사용할 수는 없고 상속받거나 익명 클래스로 객체 생성 (여기서는 익명 클래스)
      • 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

참고자료

유튜브 - 슬기로운 코딩 생활