-
[Android 개발 종합반] 2주차 - 로또번호생성기안드로이드 2024. 2. 27. 16:46
✏️ TIL(Today I Learned)
app:layout_constraint 관련 속성은 ConstraintLayout에서 뷰를 배치하는 데 사용되는 속성들이다. ConstraintLayout은 다른 뷰들과의 관계에 따라 뷰의 위치와 크기를 지정한다. 이를 위해 app:layout_constraint 속성을 사용하여 뷰 간의 제약 조건을 설정한다. ConstraintLayout은 다양한 디바이스 크기와 화면 방향에 대해 유연하게 대응할 수 있다는 장점이 있다.
더보기app:layout_constraintTop_toTopOf: 뷰의 상단을 다른 뷰의 상단에 맞춘다.
app:layout_constraintBottom_toBottomOf: 뷰의 하단을 다른 뷰의 하단에 맞춘다.
app:layout_constraintStart_toStartOf: 뷰의 시작 부분을 다른 뷰의 시작 부분에 맞춘다.
app:layout_constraintEnd_toEndOf: 뷰의 끝 부분을 다른 뷰의 끝 부분에 맞춘다.
app:layout_constraintHorizontal_bias: 가로 방향의 정렬을 설정합니다. 0이면 왼쪽 정렬, 1이면 오른쪽 정렬, 0.5이면 가운데 정렬.
app:layout_constraintVertical_bias: 세로 방향의 정렬을 설정합니다. 0이면 위쪽 정렬, 1이면 아래쪽 정렬, 0.5이면 중앙 정렬.
app:layout_constraintVertical_weight: 세로 방향의 가중치를 설정.
app:layout_constraintHorizontal_weight: 가로 방향의 가중치를 설정.
app:layout_constraintWidth_percent: 부모 뷰의 너비에 대한 비율을 설정.
app:layout_constraintHeight_percent: 부모 뷰의 높이에 대한 비율을 설정.처음 안드로이드에 관해 배울 때 주로 LinearLayout을 많이 사용해서, 주로 버튼 두개를 가로로 배치할 때 주로 아래와 같이 코드를 작성했었다.
<LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal"> <Button android:id="@+id/btn_run" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:text="자동 생성" /> <Button android:id="@+id/btn_clear" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:text="초기화" /> </LinearLayout>
오늘의 강의에서는 ConstraintLayout를 사용했는데 버튼을 배치할 때, LinearLayout 다르게 배치하는 방법을 배웠다. 굳이 레이아웃으로 감싸지 않아도 된다는 점이 편리하다.
<Button android:id="@+id/btn_run" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_marginLeft="16dp" android:layout_marginBottom="16dp" android:text="자동 생성 시작" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toStartOf="@+id/btn_clear" app:layout_constraintStart_toStartOf="parent" /> <Button android:id="@+id/btn_clear" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginStart="16dp" android:layout_marginLeft="16dp" android:layout_marginEnd="16dp" android:layout_marginRight="16dp" android:layout_marginBottom="16dp" android:text="초기화" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toEndOf="@+id/btn_run" />
📝 공부한 Kotlin 요약 정리
- by lazy: Kotlin에서 지연 초기화를 수행하는 데 사용되는 특별한 프로퍼티 위임
이를 통해 변수를 처음으로 사용할 때까지 초기화를 지연시킬 수 있다. 뷰가 실제로 필요할 때까지 초기화를 수행하지 않아서 자원 소비를 줄이고 성능을 향상시키는 데 유용하다. - ContextCompat.getDrawable(): 안드로이드에서 Drawable 리소스를 가져오는 메소드
다음과 같이 사용하며 context는 현재 컨텍스트를 나타내는 변수이고, R.drawable.my_drawable은 가져오려는 Drawable 리소스의 ID이다.
- val drawable = ContextCompat.getDrawable(context, R.drawable.my_drawable)
- when{}: Kotlin의 제어 흐름 구조 중 하나로, Java의 switch 문과 유사한 기능을 제공
when을 사용하면 다양한 조건을 지정하여 해당하는 블록을 실행할 수 있다. 예를 들어, 정수 값에 따라 다른 동작을 수행하는 코드를 작성할 수 있다. 또한 when은 다양한 타입의 값에 대해 패턴 매칭을 지원하므로, 객체의 타입이나 범위에 따라 다른 동작을 수행할 수도 있다.when (조건) { 값1 -> { // 조건이 값1과 일치할 때 실행할 코드 } 값2 -> { // 조건이 값2와 일치할 때 실행할 코드 } else -> { // 어떤 값과도 일치하지 않을 때 실행할 코드 } }
- forEach{}: Kotlin의 컬렉션에 대한 확장 함수로, 각 요소에 대해 주어진 동작을 수행
아래 코드의 forEach는 numbers 리스트의 각 요소에 대해 주어진 람다 식을 실행해 리스트의 모든 요소가 출력한다.val numbers = listOf(1, 2, 3, 4, 5) numbers.forEach { println(it) }
- forEachIndexed{}: 인덱스와 함께 각 요소에 대해 작업을 수행
이를 통해 요소의 값 뿐만 아니라 해당 요소의 인덱스에도 접근할 수 있습니다. 아래 코드에서 forEachIndexed는 numbers 리스트의 각 요소와 해당 요소의 인덱스에 대해 주어진 람다 식을 실행한다.val numbers = listOf(1, 2, 3, 4, 5) numbers.forEachIndexed { index, value -> println("Index: $index, Value: $value") }
🔎 전체 코드
class MainActivity : AppCompatActivity() { // 각 버튼과 넘버 피커에 대한 참조를 지연 초기화로 선언 private val clearButton by lazy { findViewById<Button>(R.id.btn_clear) } private val addButton by lazy { findViewById<Button>(R.id.btn_add) } private val runButton by lazy { findViewById<Button>(R.id.btn_run) } private val numPick by lazy { findViewById<NumberPicker>(R.id.np_num) } // 선택된 숫자를 나타내는 텍스트 뷰 리스트 private val numTextViewList : List<TextView> by lazy { listOf<TextView>( findViewById(R.id.tv_num1) ,findViewById(R.id.tv_num2) ,findViewById(R.id.tv_num3) ,findViewById(R.id.tv_num4) ,findViewById(R.id.tv_num5) ,findViewById(R.id.tv_num6)) } // 룰렛을 돌린 여부 변수 private var didRun = false // 선택된 숫자들의 집합 private val pickNumSet = hashSetOf<Int>() override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) // 넘버 피커의 범위를 설정 numPick.minValue = 1 numPick.maxValue = 45 // 각 버튼에 대한 초기화 initRunButton() initAddButton() initClearButton() } // 넘버 피커로 번호를 추가하는 버튼 클릭리스너 private fun initAddButton() { addButton.setOnClickListener { when { didRun -> showToast("초기화 후에 시도해주세요.") pickNumSet.size >= 6 -> showToast("최대 6개까지 선택할 수 있습니다.") pickNumSet.contains(numPick.value) -> showToast("이미 선택한 숫자입니다.") else -> { // 선택된 숫자를 텍스트 뷰에 표시하고 배경색을 설정 val textView = numTextViewList[pickNumSet.size] textView.isVisible = true textView.text = numPick.value.toString() setNumBack(numPick.value, textView) pickNumSet.add(numPick.value) } } } } // 텍스트 뷰의 배경색을 설정 private fun setNumBack(number: Int, textView: TextView) { val background = when (number) { in 1..10 -> R.drawable.circle_yellow in 11..20 -> R.drawable.circle_blue in 21..30 -> R.drawable.circle_red in 31..40 -> R.drawable.circle_gray else -> R.drawable.circle_green } textView.background = ContextCompat.getDrawable(this, background) } // 초기화 버튼 클릭리스너 private fun initClearButton() { clearButton.setOnClickListener { // 선택된 숫자들과 텍스트 뷰들을 초기화 pickNumSet.clear() numTextViewList.forEach { it.isVisible = false } didRun = false numPick.value = 1 } } // 자동생성 버튼 클릭리스너 private fun initRunButton() { runButton.setOnClickListener { // 랜덤한 숫자들을 선택하여 텍스트 뷰에 표시 val list = getRandom() didRun = true list.forEachIndexed { index, number -> val textView = numTextViewList[index] textView.text = number.toString() textView.isVisible = true setNumBack(number, textView) } } } // 중복되지 않은 랜덤한 숫자 리스트를 생성 private fun getRandom(): List<Int> { val numbers = (1..45).filter { it !in pickNumSet } return (pickNumSet + numbers.shuffled().take(6 - pickNumSet.size)).sorted() } // 토스트 메시지 private fun showToast(message: String) { Toast.makeText(this, message, Toast.LENGTH_SHORT).show() } }
'안드로이드' 카테고리의 다른 글
[Kotlin 문법 강의] 3주차: Kotlin 객체 지향 프로그래밍의 기초 (0) 2024.03.06 [Kotlin 문법 강의] 2주차: Kotlin 프로그래밍의 기초 (0) 2024.03.05 [Kotlin 문법 강의] 1주차: Kotlin을 시작하기 전에 알아야할 내용 (0) 2024.03.05 [Android 개발 종합반] 3주차 - Mbti 테스트 (뷰페이저 ViewPager2) (0) 2024.02.28 [Android 개발 종합반] 1주차 - BMI 계산기 (뷰 바인딩 View binding) (0) 2024.02.26 - by lazy: Kotlin에서 지연 초기화를 수행하는 데 사용되는 특별한 프로퍼티 위임