뷰 이벤트는 일정한 구조에 따라 처리된다. 터치 이벤트는 이벤트 콜백 함수인 onTouchEvent()
만 액티비티에 선언해 놓으면 처리할 수 있다. 키 이벤트는 이벤트 콜백 함수은 onKeyDown()
만 액티비티에 선언해 놓으면 이벤트를 처리할 수 있다. 그런데 뷰 이벤트는 이벤트 콜백 함수만 선언해서 처리할 수 없다.
뷰 이벤트 처리는 이벤트 소스(event source) 와 이벤트 핸들러(event handler) 로 역할이 나뉘며 리스너(listener) 로 연결해야 이벤트를 처리할 수 있다.
즉, 이벤트 소스에 리스러로 이벤트 핸들러를 등록해 놓으면 이벤트가 발생할 때 실행되는 구조이다.
여기서 chcekbox
객체가 이벤트가 발생하는 이벤트가 발생하는 이벤트 소스이며, 이벤트 처리 내용이 담긴 이벤트 핸들러는 OnCheckedChangeListener
인터페이스를 구현한 객체이다.
- 체크박스 이벤트 처리
binding.checkBox.setOnCheckedChangeListener(object : CompoundButton.OnCheckedChangeListener{ override fun onCheckedChanged(p0: CompoundButton?, p1: Boolean) { Log.d("태그", "onCheckedChanged 체크박스 클릭") } })
대부분 이벤트 핸들러는 이름 형식이 OnXXXListener인 인터페이스를 구현해서 만든다. 예) OnClickListener
, OnLongClickListener
, OnItemClickListener
등을 제공한다.
위 코드에서는 이벤트 핸들러를 이벤트 소스에 등록하기 위해 리스너인 setOnCheckedChangeListener()
라는 함수를 사용했다.
인터페이스로 구현한 object
클래스를 이벤트 핸들러로 만들었지만, 액티비티 자체에서 인터페이스를 구현할 수도 있다. 또한, 이벤트 핸들러를 별도의 클래스로 만들어 처리할 수 있고, 코들린의 SAM 기법을 이용할 수 있다.
(SAM : single abstract method, 코틀린 코드에서 자바 인터페이스를 간단하게 사용하기 위해 제공하는 기법)
- 액티비티에서 인터페이스를 구현한 예
// class MainActivity3 : AppCompatActivity(), CompoundButton.OnCheckedChangeListener { override fun onCreate(savedInstanceState : Bundle?){ super.onCreate(savedInstanceState) val binding = ActivityMain3Binding.inflate(layoutInflater) setContentView(binding.root) // binding.checkBox.setOnCheckedChangeListerner(this) // } override fun onCheckedChanged(p0: CompoundButton?, p1: Boolean) { Log.d("TAG", "onCheckedChanged 체크박스 클릭") } }
- 이벤트 핸들러를 별도의 클래스로 만든 예
class MyEventHandler : CompoundButton.OnCheckedChangeListener { override fun onCheckedChanged(p0: CompoundButton?, p1: Boolean) { Log.d("TAG", "onCheckedChanged 체크박스 클릭") } } class MainActivity3 : AppCompatActivity() { override fun onCreate(savedInstanceState : Bundle?){ super.onCreate(savedInstanceState) val binding = ActivityMain3Binding.inflate(layoutInflater) setContentView(binding.root) // binding.checkBox.setOnCheckedChangeListerner(MyEventHandler()) // } }
- SAM 기법으로 구현한 예
class MainActivity3 : AppCompatActivity() { override fun onCreate(savedInstanceState : Bundle?){ super.onCreate(savedInstanceState) val binding = ActivityMain3Binding.inflate(layoutInflater) setContentView(binding.root) // binding.checkBox.setOnCheckedChangeListerner { compoundButton, b -> Log.d("TAG", "onCheckedChanged 체크박스 클릭") } // } }
안드로이드 대부분의 뷰에서는 자체 이벤트를 제공한다. 그리고 아무리 뷰가 많아도 이벤트 처리 구조는 같다. 그러므로 이벤트 소스로 이벤트 핸들러를 리스너로 연결하는 구조만 이해한다면 어떤 뷰 이벤트라도 어렵지 않게 처리할 수 있다.
대표적으로 짧게 클릭할 때 발생하는 ClickEvent
와 길게 클릭할 때 발생하는 LongClickEvent
가 있다.
open fun setOnClickListener(l : View.OnClickListener?) : Unit
open fun setOnLongClickListener(l : View.OnLongClickListener?) : Unit
ClickEvent
는 OnClickListerner
를 구현한 객체를 이벤트 핸들러로,
ClickListener
는 OnLongClickListener
를 구현한 객체를 이벤트 핸들러로 등록해야 한다.
- 버튼의 클릭, 롱클릭 이벤트 처리
binding.button.setOnClickListener { Log.d("TAG", "클릭 이벤트") } binding.button.setOnLongClickListener { Log.d("TAG", "클릭 이벤트") true }