1. CheckBox
CheckBox는 여러 개의 선택사항을 사용자에게 제공한다는 측면에서 RadioButton과 동일하지만 여러 개를 동시에 선택할 수 있다는 점이 다릅니다. 별도로 언급하지는 않겠지만 ToggleButton이나 Switch도 생긴 모양에 따라 용도에 맞게 끔 사용하면 될 뿐 특별히 달라질 건 없습니다. 이는 같은 CompoundButton에서 상속받아 만들어진 위젯이기에 가능한 일인데 아래 설명에서는 CheckBox위주로 설명이 이루어지지만 기본개념과 사용방법은 같으므로 참고하시기 바랍니다.
위에서 처럼 CheckBox를 배치한뒤 각각의 속성에서 ID는 chkAir, chkShip, chkCar로 변경하고 Text를 비행기, 배, 자동차로 변경합니다.
이제 CheckBox의 체크상태 변화를 어떻게 처리할 수 있을지 알아보겠습니다. 우선 소스코드로 이동해서 chkAir의 setOnCheckedChangeListener를 작성합니다. 아래와 같이 자동완성 코드에서 CompoundButton?, Boolean이 들어간 코드를 선택하면 됩니다.
그리고 다음과 같이 코드를 작성합니다.
chkAir.setOnCheckedChangeListener{btn, isCheck ->
if (isCheck)
Log.d("test", "비행기 선택")
else
Log.d("test", "비행기 선택 해제")
}
btn은 리스너가 구현된 CheckBox자체를 나타내며 isCheck는 CheckBox의 체크상태 여부를 나타냅니다. 명칭은 어떤 걸 해도 상관없으나 첫 번째 파라미터는 위젯 자체를 두 번째는 체크상태를 나타낸다는 점만 알아두고 적절하게 명칭을 정해서 사용하면 됩니다.
위와 같은 방법으로 나머지 리스너도 구현하면 다음과 같이 할 수 있을 것입니다.
chkAir.setOnCheckedChangeListener{btn, isCheck ->
if (isCheck)
Log.d("test", "비행기 선택")
else
Log.d("test", "비행기 선택 해제")
}
chkShip.setOnCheckedChangeListener{btn, isCheck ->
if (isCheck)
Log.d("test", "배 선택")
else
Log.d("test", "배 선택 해제")
}
chkCar.setOnCheckedChangeListener{btn, isCheck ->
if (isCheck)
Log.d("test", "자동차 선택")
else
Log.d("test", "자동차 선택 해제")
}
이 방법은 CheckBox하나당 하나의 리스너를 그대로 구현하는 방법인데 직관적이긴 하지만 CheckBox가 늘어나면 그 만큼 리스너의 본체를 모두 구현해야 한다는 단점이 있습니다. 그래서 대부분은 리스너를 하나만 구현해 두고 각 위젯의 리스너를 구현된 리스너로 연결하여 처리하는 방법을 사용합니다.
var lister = CompoundButton.OnCheckedChangeListener { buttonView, isChecked ->
if (isChecked) {
when (buttonView.id) {
R.id.chkAir -> Log.d("test", "비행기 선택")
R.id.chkShip -> Log.d("test", "배 선택")
R.id.chkCar -> Log.d("test", "자동차 선택")
}
}
else {
when (buttonView.id) {
R.id.chkAir -> Log.d("test", "비행기 선택 해제")
R.id.chkShip -> Log.d("test", "배 선택 해제")
R.id.chkCar -> Log.d("test", "자동차 선택 해제")
}
}
}
본래 CheckBox는 CompoundButton에서 상속되어 만들어진 위젯으로 부모격인 CompoundButton의 리스너를 구현한 것입니다. 이제 위 리스너를 다음과 같이 각 위젯의 리스너로 연결합니다.
chkAir.setOnCheckedChangeListener(lister)
chkShip.setOnCheckedChangeListener(lister)
chkCar.setOnCheckedChangeListener(lister)
2. ProgressBar
흔히 진행상태를 나타내는 데 사용되는 ProgressBar는 자체적으로 진행상태를 위한 특별한 기능을 가지고 있지는 않습니다. 단지 ProgressBar를 보여주는 것만으로 이미 ProgressBar가 동작하고 있어서 흔히 무엇인가 상태를 나타내는 경우 표시하고 그렇지 않으면 숨기는 방법으로 사용될 수 있습니다.
간단히 사용예제를 알아보기 위해 우선 위와 같이 ProgressBar를 배치한 후 ProgressBar를 숨기거나 표시하는 함수 하나를 다음과 같이 만들어 둡니다.
fun showStatus(show: Boolean) {
if (show)
progressBar.visibility = View.VISIBLE
else
progressBar.visibility = View.GONE
}
그리고 앱이 실행될때 가상의 대기시간으로 약 3초간 ProgrssBar를 표시하다가 자동으로 화면에서 보이지 않게 코드를 작성합니다.
thread(start = true) {
Thread.sleep(3000)
runOnUiThread {
showStatus(false)
}
}
프로그램에서 스레드(thread)라는 개념은 별도의 처리를 분리해서 실행되는 것을 말합니다. Android Studio도 마찬가지인데 thread() 라는 함수는 내부에 들어간 코드를 백그라운드로 실행하도록 합니다. 그래서 Thread.sleep함수를 통해 3초(1000=1초) 간 처리를 중단하는 코드는 백그라운드에서 실행됩니다.
만약 thread()함수없이 곧바로 Thread.sleep를 호출하게 된다면 아예 메인 스레드가 중단되어 버리므로 그동안은 ProgressBar위젯을 화면에 표시조차 할 수 없게 되어 제대로 앱을 동작시킬 수 없습니다. 메인 스레드는 화면을 그려주는 동작을 전담하고 있기 때문입니다.
이 때문에 showStatus함수를 호출해서 실제 ProgressBar의 보임/숨김 여부를 처리하는 때에는 runOnUiThread로 묶어서 메인 스레드에서 ProgressBar를 직접 처리할 수 있도록 하였습니다. 간혹 메인 스레드를 화면처리에서 구분하기 위해 UI스레드라 표현하기도 합니다.
위와 같이 코드를 작성하고 앱을 실행시키면 3초 후에 ProgressBar가 사라지는 것을 볼 수 있습니다.
'Mobile > Kotlin' 카테고리의 다른 글
[Kotlin] 위젯 - SeekBar, RatingBar (0) | 2020.12.17 |
---|---|
[Kotlin] 시작하기 (hello world) (0) | 2020.12.16 |
[Kotlin] 위젯 - RadioGroup (0) | 2020.12.15 |
[Kotlin] 위젯 - ImageButton (0) | 2020.12.15 |
[Kotlin] 위젯 - Plain Text (0) | 2020.12.14 |