OnItemClickListener
adapterView가 클릭되었을 때 사용되어지는 인터페이스이다.
Single Abstract Method이기 때문에 람다로 바로 사용 가능하다.
listView.OnItemClickListener {
parent: AdapterView, view: View!, position: Int, id: Long ->
val item = parent.getItemAtPosition(position) as Movie
val intent = Intent(this, MovieDetail::class.java)
intent.putExtra(MOVIE_KEY, item)
startActivity(intent)
}
위와 같이 작성했다.
리스트뷰의 position번째에 있는 item을 클릭하면 해당 item을 intent로 다른 액티비티로 넘기는 작업이었다.
하지만 동작하지 않았다..
로그로 찍어봤는데 아예 이 함수 자체가 실행되지않는 상태였다.
(리스트뷰를 클릭해도 함수가 실행되지 않았다.)
검색해보니 두 가지를 찾아볼 수 있었다.
해당 리스트뷰가 아닌 그 안쪽에 있는 각각의 뷰들을 클릭하는 것으로 인식하고 있다.
android:descendantFocusability="blocksDescendants”
item 레이아웃의 루트에 위의 코드 추가하여 리스트뷰에 focus를 맞춘다.
focus를 가질 View를 찾을 때 ViewGroup과 그 자식들 사이의 관계를 정의한다.
1. afterDescendants: 자식들이 focus를 원하지 않을 때만 ViewGroup이 focus를 가진다. = 자식들이 먼저 focus를 가진다.
2. beforeDescendants: 자식들보다 먼저 focus를 가진다.
3. blocksDescendants: 자식들이 focus를 가지지 못하게 한다.
blocksDescendants를 주어 리스트뷰가 가진 여러 view들이 focus를 가지지 못하게 하여 리스트뷰 자체가 focus를 가지게 된다.
나의 경우 버튼이 있어서 되지 않았다.
android:focusable="false"
위의 코드를 버튼에 추가해주었더니 동작했다.
두 가지 해결방법 모두 focus와 관련이 되어있어서 찾아보았다.
focusable의 속성이 true로 되어 있는 뷰가 사용자와 상호작용하게 된다면 해당 뷰가 focus를 가졌다고 한다.
예를 들어 EditText를 사용자가 클릭하여 글을 입력할 수 있게 되면 그 EditText가 focus를 가진다.
focus를 가질 수 있는 뷰가 여러개 있다면 가장 첫 번째 뷰가 focus를 갖게 된다.
EditText나 Button같이 디폴트로 focusable한 뷰도 있지만 그렇지 않은 뷰나 레이아웃에 focus를 주고 싶다면 임의로 코드를 작성해주어야 한다.
android:focusable="true"
과 android:focusableInTouchMode="true"
를 추가해주면 focus를 줄 수 있다.
1. focusable: 말 그대로 focus를 가질 수 있냐 못가지냐의 속성을 의미하고
2. focusableInTouchMode: 사용자의 클릭으로 focus를 가질 수 있느냐를 의미한다.
어쨌튼 이와 같이 리스트뷰가 가진 하위 뷰들 중 focusable한 Button이 있었기 때문에 OnItemClickListener가 동작하지 않았던 것이다!
버튼을 클릭하면 액티비티를 띄우고 싶은데 리스트뷰 전체에 클릭이 들어가는 상황이다.
SetOnItemClickListener를 사용하려고 한 이유가 adapter 내부에서 모든 버튼마다 미리 클릭 이벤트를 등록해주고 싶지 않았기 때문이었다.
adapter 외부에서 클릭 이벤트를 처리해 주어 Event 감지 후 실행되는 콜백 등록하려 하였다.
하지만 애초에 이 인터페이스가 adapterView 전체에 반응하는 아이였기 때문에 내가 원하는대로 할 수 없었다.
결국 크루의 도움을 받아 해결하게 되었다.
결론적으로 SetOnItemClickListener는 사용하지 않았다ㅎㅎㅎ
→ adapter 생성자에 리스너 혹은 함수를 넘겨주어 adapter 내부에서 클릭했을 시 해당 리스너(함수)를 사용하도록 한다.
매번 모든 버튼에 클릭 기능을 등록해주지 않고 클릭했을 때 해당 리스너(함수)를 통해 클릭 이벤트가 실행된다.
val movieAdapter = MovieAdapter(
setMovieData(),
object : MovieAdapter.OnClickItem {
override fun onClick(movie: MovieUIModel) {
val intent = Intent(this@MovieListActivity, MovieDetailActivity::class.java)
intent.putExtra(MOVIE_KEY, movie)
startActivity(intent)
}
},
::clickAdvertisement
)
참고
https://paulaner80.tistory.com/42
https://m.blog.naver.com/PostView.naver?isHttpsRedirect=true&blogId=twotoedsloth&logNo=220015258451
https://satisfactoryplace.tistory.com/9