(코틀린 kotlin) 로또번호생성기 앱
목표 : 총 6개의 숫자를 랜덤으로 만들 수 있는 로또 번호 생성기 앱을 제작
< 세부 사항 >
1~10은 노란색 10~20은 파란색 등 숫자별로 Background Color값이 달라야함,
초기화 버튼시 만든 로또 번호는 다 지워짐
번호를 수동으로 추가할 수 있음,
먼저 레이아웃을 그리기 위해 ContraintLayout을 만들어 준다.
NumberPicker를 그려주어 1부터 45까지 선택이 가능한 코드 작성
val numberpick = findviewbyId(R.id.number_pick)
numberpick.minValue = 0
numberpick.maxValue = 45
numberpicker Layout의 위치
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
이렇게 설정하면 가운데 위치에 설정이 된다.
번호추가하기 / 초기화 버튼은
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintBaseline_toBottomOf="@id/NumberPicker"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toStartOf="@id/resetButton"
android:text="@string/Add_Button"
android:id="@+id/addButton"
app:layout_constraintHorizontal_chainStyle="packed"
android:layout_marginRight="16dp"
app:layout_marginBaseline="15dp"
>
</Button>
<Button
android:id="@+id/resetButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintStart_toEndOf="@id/addButton"
app:layout_constraintTop_toTopOf="@id/addButton"
app:layout_constraintEnd_toEndOf="parent"
android:text="@string/Reset_Button"
>
</Button>
여기서 핵심은 chainStyle 둘은 chain으로 이루어져 있어 번호 추가하기 버튼에 margin값을 설정할시 연결된 초기화 버튼에도 margin값이 같이 적용이 된다. 그리고 constraintLayout의 특징으로 위치를 지정해줄 수 있는데 여기서는
baseline으로 numberpicker의 아래에 위치를 하게 하였고 번호 추가 버튼의 end부분은 resetButton이 시작하는 위치에 있도록 설정을 해주었다.
그리고 각 번호는 LinearLayout으로 6개를 만들어 줌,
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintTop_toBottomOf="@id/addButton"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
android:layout_marginTop="20dp"
app:layout_constraintWidth="0dp"
android:gravity="center"
>
<TextView
android:gravity="center"
android:background="@drawable/circle_blue"
android:textColor="@color/white"
android:id="@+id/first_number"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="19sp"
android:text="1"
tools:visibility="visible"
android:visibility="gone"
android:layout_margin="5dp"
android:textStyle="bold">
</TextView>
<TextView
android:gravity="center"
android:background="@drawable/circle_red"
android:textColor="@color/white"
android:id="@+id/second_number"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="19sp"
android:text="1"
tools:visibility="visible"
android:visibility="gone"
android:layout_margin="5dp"
android:textStyle="bold">
</TextView>
<TextView
android:gravity="center"
android:background="@drawable/circle_yellow"
android:textColor="@color/white"
android:id="@+id/third_number"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="19sp"
android:text="1"
tools:visibility="visible"
android:visibility="gone"
android:layout_margin="5dp"
android:textStyle="bold">
</TextView>
<TextView
android:gravity="center"
android:background="@drawable/circle_green"
android:textColor="@color/white"
android:id="@+id/fourth_number"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="19sp"
android:text="1"
tools:visibility="visible"
android:visibility="gone"
android:layout_margin="5dp"
android:textStyle="bold">
</TextView>
<TextView
android:gravity="center"
android:background="@drawable/circle_gray"
android:textColor="@color/white"
android:id="@+id/fifth_number"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="19sp"
android:text="1"
tools:visibility="visible"
android:visibility="gone"
android:layout_margin="5dp"
android:textStyle="bold">
</TextView>
<TextView
android:gravity="center"
android:background="@drawable/circle_blue"
android:textColor="@color/white"
android:id="@+id/sixth_number"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="19sp"
android:text="1"
tools:visibility="visible"
android:visibility="gone"
android:layout_margin="5dp"
android:textStyle="bold">
</TextView>
</LinearLayout>
그리고 이제 Layout 구성은 끝났고 구현코드를 본다.
private val clearButton: Button by lazy{
findViewById<Button>(R.id.resetButton)
}
private val addButton: Button by lazy{
findViewById<Button>(R.id.addButton)
}
private val runButton: Button by lazy{
findViewById<Button>(R.id.runButton)
}
private val numberPicker: NumberPicker by lazy{
findViewById<NumberPicker>(R.id.NumberPicker)
}
private var didrun = false
private val pickNumberSet = mutableSetOf<Int>()
먼저 버튼과 numberPicker등 기능 설정을 위해 mainActivity에서 findviewbyid로 불러옴,
private val numberTextViewList : List<TextView> by lazy{
listOf<TextView>(
findViewById<TextView>(R.id.first_number),
findViewById<TextView>(R.id.second_number),
findViewById<TextView>(R.id.third_number),
findViewById<TextView>(R.id.fourth_number),
findViewById<TextView>(R.id.fifth_number),
findViewById<TextView>(R.id.sixth_number),
)
TextView 를 List형식으로 저장하여 numberTextViewList에 저장,
자동생성버튼
private fun initRunButton(){
runButton.setOnClickListener{
val list = getRandomNumber()
list.forEachIndexed{
index, number ->
var textView = numberTextViewList[index]
textView.text = number.toString()
textView.isVisible = true
setNumberBackground(number, textView)
}
}
}
private fun getRandomNumber() : List<Int> {
val numberList = mutableListOf<Int>().apply {
for (i in 1..45){
if (pickNumberSet.contains(i)){
continue
}
this.add(i)
}
}
numberList.shuffle()
val newList = pickNumberSet.toList() + numberList.subList(0,6-pickNumberSet.size)
return newList.sorted()
}
자동으로 번호를 생성하는 코드, setonclickListener이용 하여 버튼클릭시 작동되도록 함
getRandomNumber()는 List<Int> 형식으로 return되도록 하는 코드,
apply란 무엇일까?
apply 사용 규칙
수신 객체 람다 내부에서 수신 객체의 함수를 사용하지 않고 수신 객체 자신을 다시 반환 하려는 경우에 apply 를 사용합니다.
수신 객체 의 프로퍼티 만을 사용하는 대표적인 경우가 객체의 초기화 이며, 이곳에 apply 를 사용합니다.
val peter = Person().apply {
// apply 의 블록 에서는 오직 프로퍼티 만 사용합니다!
name = "Peter"
age = 18
}
따라서 this.add(i)를 통하여 자기자신에게 로또 번호를 추가,
private fun setNumberBackground(number:Int, textview:TextView){
when(number){
in 1..10 -> textview.background = ContextCompat.getDrawable(this, R.drawable.circle_yellow)
in 11..20 -> textview.background = ContextCompat.getDrawable(this, R.drawable.circle_blue)
in 21..30 -> textview.background = ContextCompat.getDrawable(this, R.drawable.circle_red)
in 31..40 -> textview.background = ContextCompat.getDrawable(this, R.drawable.circle_gray)
else -> textview.background = ContextCompat.getDrawable(this, R.drawable.circle_green)
}
}
setNumberBackground에 매개변수가 들어오면 number의 수 만큼 backgroundColor를 결정해주는 when문이 작성된다.
private fun initResetButton(){
clearButton.setOnClickListener{
pickNumberSet.clear()
numberTextViewList.forEach{
it.isVisible = false
}
didrun = false
}
}
private fun initAddButton(){
addButton.setOnClickListener{
if(didrun){
Toast.makeText(this,"초기화 후에 시도해 주세요",Toast.LENGTH_SHORT).show()
return@setOnClickListener
}
if(pickNumberSet.size >= 6){
Toast.makeText(this,"번호는 6개까지 선택가능 합니다.",Toast.LENGTH_SHORT).show()
return@setOnClickListener
}
if(pickNumberSet.contains(numberPicker.value)){
Toast.makeText(this,"이미 선택한 번호 입니다.",Toast.LENGTH_SHORT).show()
return@setOnClickListener
}
val textView = numberTextViewList[pickNumberSet.size]
textView.isVisible = true
textView.text = numberPicker.value.toString()
setNumberBackground(numberPicker.value, textView)
pickNumberSet.add(numberPicker.value)
}
}
마지막으로 add버튼과 reset버튼 foreach를 사용하면 it.~~식으로 layout접근 가능하다.
이렇게 앱이 완성됐다.