티스토리 뷰

728x90
반응형
SMALL

앞서 만든 기본적인 로또 앱을 응용하여 더 다양하고 사용자 친화적인 기능을 추가해보겠습니다. 이번 예제에서는 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>

728x90
반응형
LIST
반응형
250x250
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/07   »
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
글 보관함