티스토리 뷰
앞서 만든 기본적인 로또 앱을 응용하여 더 다양하고 사용자 친화적인 기능을 추가해보겠습니다. 이번 예제에서는 UI를 더 강화하여 사용자 경험을 향상시킬 것입니다.
Kotlin 코드 작성
1. 로또 번호 생성 로직: MainActivity.kt 파일을 열어 로또 번호를 생성하는 비즈니스 로직을 작성합니다.
// MainActivity.kt
import android.os.Bundle
import android.util.Log
import android.widget.Button
import androidx.appcompat.app.AppCompatActivity
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
class MainActivity : AppCompatActivity() {
private lateinit var generateLottoButton: Button
private lateinit var recyclerView: RecyclerView
private val TAG = this::class.java.simpleName
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
generateLottoButton = findViewById(R.id.generateLottoButton)
recyclerView = findViewById(R.id.recyclerView)
generateLottoButton.setOnClickListener {
val numberOfLists = 5
val lottoLists = Utils.generateMultipleLottoLists(numberOfLists)
// 결과 출력
for ((index, lottoList) in lottoLists.withIndex()) {
Log.d(TAG, "리스트 ${index + 1}: $lottoList")
}
val recyclerView = recyclerView
recyclerView.layoutManager = LinearLayoutManager(this)
val adapter = NumberAdapter(lottoLists)
recyclerView.adapter = adapter
adapter.notifyDataSetChanged()
}
}
}
1.1 클래스 및 변수 선언
class MainActivity : AppCompatActivity() {
private lateinit var generateLottoButton: Button
private lateinit var recyclerView: RecyclerView
private val TAG = this::class.java.simpleName
}
위 코드에서 MainActivity 클래스는 AppCompatActivity를 상속받아 안드로이드 앱의 메인 화면을 담당합니다. generateLottoButton은 "로또 생성" 버튼을 나타내며, recyclerView는 로또 번호를 표시할 RecyclerView입니다.
1.2. onCreate 메서드
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
}
onCreate 메서드는 액티비티가 생성될 때 호출되며, 화면 초기화 및 기본 설정을 수행합니다.
1.3. UI 요소 초기화
generateLottoButton = findViewById(R.id.generateLottoButton)
recyclerView = findViewById(R.id.recyclerView)
XML 레이아웃에서 정의한 UI 요소들을 찾아와 각 변수에 할당합니다.
1.4. 버튼 클릭 이벤트 처리
generateLottoButton.setOnClickListener {
val numberOfLists = 5
val lottoLists = Utils.generateMultipleLottoLists(numberOfLists)
// 결과 출력
for ((index, lottoList) in lottoLists.withIndex()) {
Log.d(TAG, "리스트 ${index + 1}: $lottoList")
}
val recyclerView = recyclerView
recyclerView.layoutManager = LinearLayoutManager(this)
val adapter = NumberAdapter(lottoLists)
recyclerView.adapter = adapter
adapter.notifyDataSetChanged()
}
"로또 생성" 버튼에 클릭 리스너를 등록하고, 클릭 시 수행될 동작을 정의합니다. 여기서 Utils.generateMultipleLottoLists(numberOfLists)를 통해 여러 개의 로또 번호 리스트를 생성하고, 생성된 리스트를 로그로 출력하며 RecyclerView에 표시합니다.
2. 로또 번호 생성기: Utils.kt 파일을 열어 로또 번호 5천원 5줄을 만드는 코드를 작성합니다.
// Utils.kt
object Utils {
fun generateMultipleLottoLists(numberOfLists: Int): List<List<Int>> {
val allLottoLists = mutableListOf<List<Int>>()
repeat(numberOfLists) {
val lottoList = setList(generateLottoNumbers())
allLottoLists.add(lottoList)
}
return allLottoLists
}
fun generateLottoNumbers(): List<Int> {
// 1부터 45까지의 숫자 리스트 생성
val numbers = (1..45).toMutableList()
// 리스트를 섞음 (무작위로 숫자 선택을 위해)
numbers.shuffle()
// 처음 6개의 숫자를 선택하고 정렬
val selectedNumbers = numbers.take(6).sorted()
return selectedNumbers
}
fun setList(initList: List<Int>): List<Int> {
// 1부터 45까지의 숫자 리스트 생성
val numbers = (1..45).toMutableList()
val finalList = (numbers + initList).distinct() - (numbers intersect initList)
// 리스트를 섞음 (무작위로 숫자 선택을 위해)
val finalmutable = finalList.toMutableList()
finalmutable.shuffle()
// 처음 6개의 숫자를 선택하고 정렬
val selectedNumbers = finalmutable.take(6).sorted()
return selectedNumbers
}
}
Utils 클래스는 여러 개의 로또 번호 리스트를 생성하고, 로또 번호를 무작위로 섞거나 기존 리스트와 중복되지 않도록 조정하는 역할을 합니다. 아래는 Utils 클래스의 주요 메서드들을 설명합니다.
2.1. generateMultipleLottoLists 메서드
fun generateMultipleLottoLists(numberOfLists: Int): List<List<Int>> {
val allLottoLists = mutableListOf<List<Int>>()
repeat(numberOfLists) {
val lottoList = setList(generateLottoNumbers())
allLottoLists.add(lottoList)
}
return allLottoLists
}
이 메서드는 주어진 개수만큼의 로또 번호 리스트를 생성하는 역할을 합니다. repeat 함수를 사용하여 generateLottoNumbers 메서드를 호출하고, 그 결과를 setList 메서드로 전달하여 리스트를 최종적으로 조정한 후, 모든 리스트를 반환합니다.
2.2. generateLottoNumbers 메서드
fun generateLottoNumbers(): List<Int> {
// 1부터 45까지의 숫자 리스트 생성
val numbers = (1..45).toMutableList()
// 리스트를 섞음 (무작위로 숫자 선택을 위해)
numbers.shuffle()
// 처음 6개의 숫자를 선택하고 정렬
val selectedNumbers = numbers.take(6).sorted()
return selectedNumbers
}
이 메서드는 1부터 45까지의 숫자 리스트를 생성하고, 이를 섞어서 무작위로 숫자를 선택합니다. 선택된 6개의 숫자는 정렬되어 반환됩니다.
2.3. setList 메서드
fun setList(initList: List<Int>): List<Int> {
// 1부터 45까지의 숫자 리스트 생성
val numbers = (1..45).toMutableList()
val finalList = (numbers + initList).distinct() - (numbers intersect initList)
// 리스트를 섞음 (무작위로 숫자 선택을 위해)
val finalMutable = finalList.toMutableList()
finalMutable.shuffle()
// 처음 6개의 숫자를 선택하고 정렬
val selectedNumbers = finalMutable.take(6).sorted()
return selectedNumbers
}
setList 메서드는 초기로 주어진 리스트에 새로운 숫자를 추가하고, 중복된 숫자를 제외하여 최종적인 리스트를 생성합니다. 이후 리스트를 섞어서 무작위로 숫자를 선택하고, 선택된 6개의 숫자를 정렬하여 반환합니다.
3. RecyclerView: NumberAdapter.kt 파일을 열어 recyclerview adapter 코드를 작성합니다.
// NumberAdpater.kt
import android.content.Context
import android.view.LayoutInflater
import android.view.ViewGroup
import android.widget.TextView
import androidx.recyclerview.widget.RecyclerView
class NumberAdapter(private val lottoLists: List<List<Int>>) :
RecyclerView.Adapter<NumberViewHolder>() {
private val TAG = this::class.java.simpleName
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): NumberViewHolder {
val itemView =
LayoutInflater.from(parent.context).inflate(R.layout.item_number, parent, false)
return NumberViewHolder(itemView)
}
override fun onBindViewHolder(holder: NumberViewHolder, position: Int) {
val lottoList = lottoLists[position]
// 각 숫자를 TextView에 설정
holder.textView1.text = lottoList[0].toString()
holder.textView2.text = lottoList[1].toString()
holder.textView3.text = lottoList[2].toString()
holder.textView4.text = lottoList[3].toString()
holder.textView5.text = lottoList[4].toString()
holder.textView6.text = lottoList[5].toString()
// 각 숫자에 대한 색상 설정
val context = holder.itemView.context
setNumberColor(context, holder.textView1, lottoList[0])
setNumberColor(context, holder.textView2, lottoList[1])
setNumberColor(context, holder.textView3, lottoList[2])
setNumberColor(context, holder.textView4, lottoList[3])
setNumberColor(context, holder.textView5, lottoList[4])
setNumberColor(context, holder.textView6, lottoList[5])
}
private fun setNumberColor(context: Context, textView: TextView, number: Int) {
val colorResId = when {
number <= 10 -> R.drawable.circle_yellow
number <= 20 -> R.drawable.circle_blue
number <= 30 -> R.drawable.circle_green
number <= 40 -> R.drawable.circle_gray
else -> R.drawable.circle_red
}
textView.setBackgroundResource(colorResId)
}
override fun getItemCount(): Int {
return lottoLists.size
}
}
NumberAdapter 클래스는 RecyclerView에 데이터를 연결하여 화면에 로또 번호 리스트를 표시하는 역할을 합니다. 아래는 NumberAdapter 클래스의 각 부분을 설명합니다.
3.1. NumberAdapter 클래스 선언 및 생성자
class NumberAdapter(private val lottoLists: List<List<Int>>) :
RecyclerView.Adapter<NumberViewHolder>() {
private val TAG = this::class.java.simpleName
...
}
NumberAdapter 클래스는 RecyclerView.Adapter 클래스를 상속받습니다. 생성자에서는 표시할 로또 번호 리스트를 받습니다.
3.2. onCreateViewHolder 메서드
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): NumberViewHolder {
val itemView =
LayoutInflater.from(parent.context).inflate(R.layout.item_number, parent, false)
return NumberViewHolder(itemView)
}
onCreateViewHolder 메서드에서는 뷰 홀더를 생성하고, 이를 반환합니다. 뷰 홀더는 각 로또 번호 리스트의 항목을 표현하는 XML 레이아웃 파일인 item_number.xml을 기반으로 생성됩니다.
3.3. onBindViewHolder 메서드
override fun onBindViewHolder(holder: NumberViewHolder, position: Int) {
val lottoList = lottoLists[position]
// 각 숫자를 TextView에 설정
holder.textView1.text = lottoList[0].toString()
holder.textView2.text = lottoList[1].toString()
holder.textView3.text = lottoList[2].toString()
holder.textView4.text = lottoList[3].toString()
holder.textView5.text = lottoList[4].toString()
holder.textView6.text = lottoList[5].toString()
// 각 숫자에 대한 색상 설정
val context = holder.itemView.context
setNumberColor(context, holder.textView1, lottoList[0])
setNumberColor(context, holder.textView2, lottoList[1])
setNumberColor(context, holder.textView3, lottoList[2])
setNumberColor(context, holder.textView4, lottoList[3])
setNumberColor(context, holder.textView5, lottoList[4])
setNumberColor(context, holder.textView6, lottoList[5])
}
onBindViewHolder 메서드에서는 뷰 홀더에 데이터를 바인딩합니다. 각 로또 번호 리스트의 숫자를 해당하는 TextView에 설정하고, setNumberColor 메서드를 사용하여 각 숫자에 대한 색상을 설정합니다.
3.4. setNumberColor 메서드
private fun setNumberColor(context: Context, textView: TextView, number: Int) {
val colorResId = when {
number <= 10 -> R.drawable.circle_yellow
number <= 20 -> R.drawable.circle_blue
number <= 30 -> R.drawable.circle_green
number <= 40 -> R.drawable.circle_gray
else -> R.drawable.circle_red
}
textView.setBackgroundResource(colorResId)
}
setNumberColor 메서드는 각 숫자에 대한 색상을 설정합니다. 숫자 범위에 따라 다른 배경색을 지정하여 시각적으로 구분되도록 합니다.
3.5. getItemCount 메서드
override fun getItemCount(): Int {
return lottoLists.size
}
getItemCount 메서드에서는 표시할 로또 번호 리스트의 총 개수를 반환합니다.
4. ViewHolder: NumberViewHolder.kt 파일을 열어 코드를 작성합니다.
class NumberViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
val textView1: TextView = itemView.findViewById(R.id.circle1)
val textView2: TextView = itemView.findViewById(R.id.circle2)
val textView3: TextView = itemView.findViewById(R.id.circle3)
val textView4: TextView = itemView.findViewById(R.id.circle4)
val textView5: TextView = itemView.findViewById(R.id.circle5)
val textView6: TextView = itemView.findViewById(R.id.circle6)
}
5. UI: res.layout.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">
<ScrollView
android:layout_width="match_parent"
android:layout_height="wrap_content">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:orientation="vertical">
<Button
android:id="@+id/generateLottoButton"
android:layout_width="150dp"
android:layout_height="150dp"
android:background="@drawable/circle_btn"
android:backgroundTint="@color/light_blue"
android:padding="16dp"
android:textColor="@color/white"
android:text="start"
android:textSize="16dp"/>
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recyclerView"
android:layout_width="wrap_content"
android:layout_height="500dp"
tools:listitem="@layout/item_number" />
</LinearLayout>
</ScrollView>
</LinearLayout>
6. UI: res.layout.item_number.xml 파일을 열어 recyclerview에 들어갈 item 코드를 작성합니다.
<?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="wrap_content"
android:layout_marginVertical="10dp"
android:orientation="vertical">
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="@color/black"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="16dp"
android:gravity="center"
android:orientation="horizontal">
<!-- 여기에 각 숫자를 개별적으로 표시할 원을 추가합니다 -->
<TextView
android:id="@+id/circle1"
android:layout_width="40dp"
android:layout_height="40dp"
android:gravity="center"
android:textColor="@android:color/white"
android:textSize="16sp"
android:layout_marginRight="8dp"/>
<TextView
android:id="@+id/circle2"
android:layout_width="40dp"
android:layout_height="40dp"
android:gravity="center"
android:textColor="@android:color/white"
android:textSize="16sp"
android:layout_marginRight="8dp"/>
<TextView
android:id="@+id/circle3"
android:layout_width="40dp"
android:layout_height="40dp"
android:gravity="center"
android:textColor="@android:color/white"
android:textSize="16sp"
android:layout_marginRight="8dp"/>
<TextView
android:id="@+id/circle4"
android:layout_width="40dp"
android:layout_height="40dp"
android:gravity="center"
android:textColor="@android:color/white"
android:textSize="16sp"
android:layout_marginRight="8dp"/>
<TextView
android:id="@+id/circle5"
android:layout_width="40dp"
android:layout_height="40dp"
android:gravity="center"
android:textColor="@android:color/white"
android:textSize="16sp"
android:layout_marginRight="8dp"/>
<TextView
android:id="@+id/circle6"
android:layout_width="40dp"
android:layout_height="40dp"
android:gravity="center"
android:textColor="@android:color/white"
android:textSize="16sp"/>
</LinearLayout>
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="@color/black"/>
</LinearLayout>
7. UI: res.layout.circle_???.xml 파일을 열어 원을 만드는 코드를 작성합니다.
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >
<item>
<shape android:shape="oval">
<solid android:color="@color/???????"/>
</shape>
</item>
</layer-list>
'안드로이드 실전' 카테고리의 다른 글
Kotlin: 안드로이드 앱 실전 개발 (1. 로또 앱 만들기) (0) | 2024.01.25 |
---|
- Total
- Today
- Yesterday
- MVVM패턴
- UI스레드
- 비동기처리
- 부동산
- 코틀린
- 디자인패턴
- RoomDatabase
- fragment생명주기
- 내부데이터베이스
- 부동산 경매
- 안드로이드앱개발
- cipher
- 모듈화
- 코루틴
- 안드로이드 앱 개발
- Fragment
- 안드로이드기초
- 비동기
- 경매
- kotlin
- 안드로이드
- RxJava
- coroutine
- 사이버보안
- 앱개발
- Android
- 기초
- 안드로이드개발
- 클린아키텍처
- 생명주기
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |