[GDSC Ewha 5th] Android Session

[GDSC Android] Chapter 4. 안드로이드 앱 만들기 (Build your first Android app) (2)

wlalsu_u 2023. 11. 8. 22:57

[ 4. 안드로이드 앱 만들기 (Build your first Android app) (1) 블로그 정리 ]

https://wlalsu.tistory.com/126

 

[GDSC Android] Chapter 4. 안드로이드 앱 만들기 (Build your first Android app) (1)

4.0 Build your first Android app 학습 목표 Google에서 빌드하고 배포하는 안드로이드 공식 IDE인 Android Studio를 이용하여 앱을 개발해보자. Android Studio를 이용하여 Dice Roller 앱 만들기 Android Studio 다운로드

wlalsu.tistory.com

 

 

 

 

 

4.4 DiceRoller 앱 구현하기

 

 

 

 

1) 프로젝트 생성하기

 

 

 

 

DiceRoller 를 만들 프로젝트를 생성해보자.

 

New Project > Empty Views Activity 를 선택한다.

 

 

 

 

 

 

 

 

 

 

 

 

Next 버튼을 클릭하면

 

새로운 프로젝트의 이름과 속성을 선택할 수 있다.

 

 

 

 

 

 

 

 

 

 

 

 

1) Name

 

- 프로젝트 이름 설정

 

- Dice Roller로 설정

 

 

2) Package Name

 

- 차후 웹으로 확장할 수도 있고, 웹 도메인 주소가 되므로 신중하게 결정

 

- DiceRoller의 경우 단순하게 com.gdsc_android.diceroller로 설정함

 

 

3) Language

 

- Kotlin으로 설정

 

 

4) Mininum SDK

 

- 최신 버전의 경우 모든 기기에서 작동되지 않을 수 있음

 

- 100% device에서 실행 가능한 API 19 버전 사용

 

 

 

 

 

 

 

 

Finish 버튼을 클릭하면

 

약간의 시간이 흐른 후 프로젝트가 생성되게 된다.

 

 

 

 

 

 

 

2) Action Bar 만들기

 

 

 

 

 

먼저 상단의 action bar를 만들어보자.

 

 

 

res > values > themes > themes.xml 파일을 연 후

 

action bar를 생성하기 위해

 

parent="Theme.AppCompat.DayNight.DarkActionBar" 로 바꾸어준다.

 

 

 

이후 @color/my_light_primary를 작성하면

 

아래와 같이 오류가 발생하게 된다.

 

 

 

 

 

 

 

 

 

 

 

 

 

이는 color resource가 없기 때문이므로

 

오류가 발생하는 코드에 커서를 놓고 Alt + Enter 누른 후

 

create color value resource 만들기를 선택한다.

 

 

 

 

 

 

 

 

 

 

 

 

 

New Color Value Resource에서

 

설정하고 싶은 색깔로 resoucre value 선택한 후,

 

OK 버튼을 클릭한다.

 

 

 

 

 

Action Bar를 생성하기 위한 최종 themes.xml 코드는 다음과 같다.

 

 

 

 

 

<resources xmlns:tools="http://schemas.android.com/tools">
    <!-- Base application theme. -->
    <style name="Base.Theme.DiceRoller" parent="Theme.AppCompat.DayNight.DarkActionBar">
        <item name="colorPrimary">@color/my_light_primary</item>
    </style>

    <style name="Theme.DiceRoller" parent="Base.Theme.DiceRoller" />

    <color name="my_light_primary">#9C27B0</color>
</resources>

 

 

 

 

 

 

 

실행 버튼을 눌러보면

 

아래와 같이 Emulator에서 상단에 액션 바가 생성되는 것을 볼 수 있다.

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

3) Layout 만들기

 

 

 

 

다음으로 앱 레이아웃을 만들어보자.

 

 

 

main의 layout을 설정할 것이기 때문에

 

activity_main.xml 파일에 들어간다.

 

 

 

 

 

 

 

 

 

 

 

Design 탭을 누르면

 

왼쪽은 실제 사진이나 버튼을 볼 수 있는 디자인 뷰( 흰색 )가 있고,

 

오른쪽에는 컴포넌트가 어느 위치에 어떤 크기를 갖고 있는지와 같은 설계뷰 ( 파란색)이 나타난다.

 

 

 

 

왼쪽의 Palette에서 버튼을 뷰에 끌어다 놓으면

 

새로운 버튼이 생성된다.

 

 

 

 

 

 

 

 

 

 

 

이후 텍스트뷰 설정에서 텍스트 명을 '굴러라!' 로 변경하였다.

 

 

 

 

 

 

 

 

 

 

 

 

 

 

실제로 상단에 Code 버튼을 클릭하여 XML 파일을 살펴보면

 

Button 코드가 생성된 것을 확인할 수 있다.

 

 

 

 

 

 

 

 

 

 

 

 

 

 

이때 하단의 경고를 살펴보면

 

버튼이 하드코드 되어 있다는 메시지를 확인할 수 있다.

 

 

 

앞서 정적데이터는 정적 데이터 value에 저장되어 있다고 하였는데,

 

'굴려라!' 라는 정적 텍스트를 직접 작성하였기 때문에 발생하는 경고이다.

 

 

 

 

 

 

 

 

 

 

 

 

 

 

하단의 경고 메시지창의 전구 버튼을 클릭한 후,

 

Extract String resource 설정하기를 누른 후,

 

이름을 'roll'로 지정해준다.

 

 

 

 

 

 

 

 

 

 

 

 

 

실제로 다시 XML 코드를 확인해보면

 

Button의 text 코드가 하드코딩되지 않고,

 

"@string/roll"로 바뀐것을 확인할 수 있다.

 

 

 

 

 

 

다음으로 버튼의 constraints를 설정해보자.

 

 

 

 

 

constraints는 위 / 아래 중 적어도 하나를 설정하고,

 

왼쪽 / 오른쪽 중에 하나를 설정해 주어야 한다.

 

(그렇지 않으면 정확한 위치를 나타낼 수 없기 때문에)

 

 

 

 

 

text 컴포넌트 사각형의 원을 클릭한 후 

 

원하는 위치로 constraints를 조정하면,

 

오른쪽 Layout 설정의 constraints 부분이 변경된 것을 확인할 수 있다.

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

4) 랜덤 주사위 숫자 보여주기

 

 

 

 

다음으로 기존에 작성되어 있던 Hello World! 부분에

 

랜덤으로 굴린 주사위의 숫자가 뜨도록 수정해보자

 

 

 

 

 

 

 

 

 

 

 

 

처음에는 주사위 숫자가 보이면 안되므로, text 자리의 글자를 삭제해준다.

 

 

 

하지만 text를 삭제하게 되면

 

개발자도 해당 위치에 주사위 결과를 표현해야 한다는 것을 알기 힘들어진다.

 

 

 

따라서 왼쪽에 공구 표시가 있는 text 설정에 '주사위 결과'라고 입력하면,

 

실제 화면에는 보이지 않지만, 

 

개발자가 해당 위치에 있는 텍스트를 확인할 수 있게 된다.

 

 

 

 

 

 

실제로 앱을 실행해보면 텍스트가 뜨지 않는 것을 확인할 수 있다.

 

 

 

 

 

 

 

 

5) 버튼을 누르면 Toast Message가 뜨도록 하기

 

 

 

 

 

레이아웃 지정이 모두 끝났으므로

 

Activity를 수정하여 버튼을 누르면 주사위가 굴려지도록 해보자.

 

 

 

 

먼저 Button의 id를 설정해주기 위해

 

activity_main.xml에서 아래와 같이 id를 rollButton으로 변경한다.

 

 

 

 

 

 

 

 

 

 

 

 

 

이후 MainActivity 파일에 들어간 후,

 

아래와 같이 주사위를 굴리는 코드를 작성한다.

 

 

 

 

 

 

package com.gdsc_android.diceroller

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.widget.Button
import android.widget.Toast

class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        val rollButton: Button = findViewById(R.id.rollButton)
        rollButton.setOnClickListener{
            Toast.makeText(this, "주사위가 굴러졌습니다.", Toast.LENGTH_SHORT).show()
        }
    }
}

 

 

 

 

 

 

1) onCreate() 함수

 

- AppCompatActivity() 의 함수를 오버라이딩

 

- MainActivity를 실행하면 처음 실행됨

 

 

2) val rollButton

 

- 앞서 작성한 버튼의 id 인 R.id.rollButton을 설정

 

 

3) setOnClickListener

 

- 버튼을 눌렀을 때 이벤트를 발생하기 위한 함수

 

 

4) Toast.makeText

 

- 버튼을 눌렀을 때 아래에 뜨는 메시지를 토스트 메시지라고 함

 

- Toast.LENGTH_SHORT로 메시지가 짧게 보여지도록 설정

 

- 마지막에 show() 를 작성하지 않으면 생성만 되고 실제로 보여지지 않음 

 

 

 

 

 

 

 

 

 

 

 

 

 

실제로 실행해보면

 

버튼을 눌렀을 때 아래에 토스트메시지가 뜨는 것을 확인할 수 있다.

 

 

 

 

 

 

 

 

 

6) 버튼을 누르면 랜덤 주사위 숫자가 뜨도록 하기

 

 

 

 

 

다음으로 버튼을 클릭하면

 

랜덤으로 주사위 숫자가 뜨도록 바꿔보자.

 

 

 

 

 

 

 

 

 

 

 

먼저 레이아웃 XML 파일을 확인해보면,

 

숫자를 나타낼 TextView의 id 가 textView인 것을 확인할 수 있다.

 

 

 

 

다음은 랜덤으로 숫자를 생성하기 위한 코드이다.

 

코드를 하나씩 자세히 살펴보자.

 

 

 

 

 

package com.gdsc_android.diceroller

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.widget.Button
import android.widget.TextView

/**
 * 본 activity는 사용자가 주사위를 굴리고 그 결과를 화면에서 볼 수 있도록 한다.
 */
class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        val rollButton: Button = findViewById(R.id.rollButton)

        rollButton.setOnClickListener{ rollDice() }
    }

    /**
     * 주사위를 굴리고 결과와 함께 화면을 업데이트 한다.
     */
    private fun rollDice() {
        // 주사위 객체 생성
        val myDice = Dice(6) // 육면체 주사위

        // 주사위 굴리기
        // 주사위 굴린 결과를 변수에 받아놓기
        val diceResult = myDice.roll()

        // TextView 가져오기
        val resultTextView: TextView = findViewById(R.id.textView)

        // TextView에 주사위 굴린 결과 출력하기
        resultTextView.text = diceResult.toString()
    }

    class Dice(private val numSides: Int) {
        fun roll(): Int {
            return (1..numSides).random()
        }
    }
}

 

 

 

 

 

 

1) onCreate() 함수

 

- 해당 버튼의 id 값을 가져와 rollButton을 생성

 

- 리스너 함수 안의 코드가 한 줄 밖에 없으므로, 함수를 한줄로 작성함

 

- rollButton을 클릭하면 rollDice() 함수를 실행하도록 함

 

 

 

2) rollDice() 함수

 

- 6면체인 myDice 주사위 객체를 생성

 

- myDice객체를 roll() 한 후, 주사위 결과를 diceResult 변수에 저장

 

- 주사위 결과를 표현할 textView의 id 값을 가져와 resultTextView를 생성함

 

- diceResult값은 Int형이므로, 이를 String으로 바꾸고 resultTextView에 저장

 

 

 

3) Dice 클래스

 

- 주사위 객체를 생성하기 위한 클래스

 

- 몇 면체인지 설정할 수 있는 파라미터 값을 받음 (외부에서 알 필요가 없으므로 private으로 설정)

 

- 1부터 파라미터로 받은 주사위 면체수 중에 랜덤으로 숫자 하나를 고름

 

 

 

 

 

 

 

 

 

 

 

 

 

실제로 결과를 확인해보면,

 

버튼을 누를 때마다 무작위로 주사위 숫자가 생성되는 것을 확인할 수 있다.

 

 

 

 

 

 

 

 

7) 버튼을 누르면 랜덤 주사위 이미지 뜨도록 하기

 

 

 

 

 

마지막으로 주사위를 굴리면 숫자가 아닌

 

실제 그림이 나오도록 수정해보자.

 

 

 

먼저 기존의 텍스트 뷰는 삭제한 후,

 

activity_main.xml에서 주사위 그림을 넣어준다.

 

 

 

 

 

 

 

 

 

 

 

 

 

Palette의 이미지 뷰를 화면에 드래그 하여 주사위 이미지를 추가한다.

 

 

 

 

 

이때 앞선 textView예시와 마찬가지로

 

첫 실행 화면에서는 주사위 그림이 보여지면 안되므로,

 

옆에 공구 아이콘이 있는 srcCompat에 이미지를 넣어 개발자만 해당 위치를 파악할 수 있도록 하자.

 

 

 

 

 

 

 

버튼을 누르면 나오는 주사위 수에 따라

 

이미지가 변경되도록 하는 코드는 아래와 같다.

 

아래의 코드를 하나씩 자세하게 살펴보자.

 

 

 

 

 

package com.gdsc_android.diceroller

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.widget.Button
import android.widget.ImageView

/**
 * 본 activity는 사용자가 주사위를 굴리고 그 결과를 화면에서 볼 수 있도록 한다.
 */
class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        val rollButton: Button = findViewById(R.id.rollButton)

        rollButton.setOnClickListener{ rollDice() }

        // activity 시작과 동시에 주사위 구르기
        rollDice()
    }

    /**
     * 주사위를 굴리고 결과와 함께 화면을 업데이트 한다.
     */
    private fun rollDice() {
        // 주사위 객체 생성
        val myDice = Dice(6) // 육면체 주사위

        // 주사위 굴리기
        // 주사위 굴린 결과를 변수에 받아놓기
        val diceResult = myDice.roll()

        // ImageView 가져오기
        val resultImageView: ImageView = findViewById(R.id.imageView2)

        // ImageView에 주사위 굴린 결과 출력하기
        val imageResource = when(diceResult){
            1 -> R.drawable.dice_1
            2 -> R.drawable.dice_2
            3 -> R.drawable.dice_3
            4 -> R.drawable.dice_4
            5 -> R.drawable.dice_5
            else -> R.drawable.dice_6
        }

        resultImageView.setImageResource(imageResource)
    }

    class Dice(private val numSides: Int) {
        fun roll(): Int {
            return (1..numSides).random()
        }
    }
}

 

 

 

 

 

 

 

1) onCreate() 함수

 

- roll() 함수를 추가하여 처음에 주사위가 자동으로 굴려지도록 함

 

 

 

2) resultImageView

 

- 주사위 이미지의 id 값을 찾은 후 이를 resultImageView로 가져옴

 

 

 

3) imageResource

 

- when 절을 이용하여 diceResult에 따라 다른 이미지가 보여지도록 함

 

- when식에는 else문이 필수적이므로, 마지막 6번은 else문으로 설정

 

( Ctrl + d를 누르면 해당 줄의 코드 복사 가능 )

 

 

 

 

 

 

 

 

 

 

 

 

 

 

실행결과를 확인해보면

 

처음 실행 시 자동으로 주사위가 한번 굴려지며,

 

이후에 버튼을 누르때마다 주사위가 랜덤으로 굴려지는 것을 확인할 수 있다.

 

 

 

 

 


 

 

 

 

 

4.5 주사위가 2개인 DiceRoller 앱 구현하기

 

 

 

 

아래는 버튼을 눌렀을 때

 

2개의 주사위가 동시에 굴려지는 MainActivity 소스코드와 결과이다.

 

 

 

 

package com.gdsc_android.diceroller

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.widget.Button
import android.widget.ImageView

/**
 * 본 activity는 사용자가 주사위를 굴리고 그 결과를 화면에서 볼 수 있도록 한다.
 */
class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        val rollButton: Button = findViewById(R.id.rollButton)

        rollButton.setOnClickListener{ rollDice() }

        // activity 시작과 동시에 주사위 구르기
        rollDice()
    }

    /**
     * 주사위를 굴리고 결과와 함께 화면을 업데이트 한다.
     */
    private fun rollDice() {
        // 주사위 객체 생성
        val myDice1 = Dice(6) // 주사위1
        val myDice2 = Dice(6) // 주사위2

        // 주사위 굴리기
        // 주사위 굴린 결과를 변수에 받아놓기
        val diceResult1 = myDice1.roll()
        val diceResult2 = myDice2.roll()

        // ImageView 가져오기
        val resultImageView1: ImageView = findViewById(R.id.imageView2)
        val resultImageView2: ImageView = findViewById(R.id.imageView3)

        // ImageView에 주사위 굴린 결과 출력하기
        val imageResource1 = when(diceResult1){
            1 -> R.drawable.dice_1
            2 -> R.drawable.dice_2
            3 -> R.drawable.dice_3
            4 -> R.drawable.dice_4
            5 -> R.drawable.dice_5
            else -> R.drawable.dice_6
        }
        val imageResource2 = when(diceResult2){
            1 -> R.drawable.dice_1
            2 -> R.drawable.dice_2
            3 -> R.drawable.dice_3
            4 -> R.drawable.dice_4
            5 -> R.drawable.dice_5
            else -> R.drawable.dice_6
        }

        resultImageView1.setImageResource(imageResource1)
        resultImageView2.setImageResource(imageResource2)

    }

    class Dice(private val numSides: Int) {
        fun roll(): Int {
            return (1..numSides).random()
        }
    }
}

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

'GDSC Android 교육 세션 자료 및 강의 내용' 과 'Codelab 3강 : Classes and objects' 내용을 기반으로 작성하였습니다.