View
오늘 알게 된 것
금일도 개발 중에 알게 된 것을 이지 않기 위해서 글을 쓴다.
TabLayout 스크롤 감지
오늘 글을 쓰게 된 이유이자 조금 낳이 고민했던 부분이다.
스크롤이 가능한 TabLayout을 구현하는 도중에 화면을 넘어가는 tabItem이 선택 되었을 때 해당 tabItem에 스크롤과 화면을 잡아 줘야되었다. 여기서 문제가 발생했다. 해당 tabItem에 선택은 되는데 해당 화면이 스크롤되어 자동적으로 화면에 보여주지 않았다.
물론 tablayout의 함수 중 setScrollPosition(index, 0f, false)[해당 아이템 인텍스, 인덱스 오프섹, updateSelectedTabView(boolean)]가 존재 했다. 즉 해당 함수를 이용하면 TabLayout의 tabItam의 Position을 찾아서 알아서 스크롤 해주는 것이다. 하지만 제대로 발동되지 않았다.
[원하는 결과]
[현재 상황]
[문제 코드]
private fun selectTabItem(category: String, index: Int) {
binding.tb.selectTab(binding.tb.getTabAt(index))
binding.tb.setScrollPosition(index, 0f, false)
viewModel.requestQuestion(category)
}
코드에 대해서 간단히 설명을 하자면
binding.tb.selectTab(binding.tb.getTabAt(index)를 통해서 TabItem중에 선택되어야 하는 TabItem을 선택되게 해주는 것이다.
binding.tb.setScrollPosition(index, 0f, false)이 부분이 선택된 TabItem으로 스크롤 되어 자동으로 화면이 이동하는 함수이다.
viewModel.requestQuestion(category)는 원하는 TabItem이 선택 되었을 때 보여줘야되는 아래 데이터이다.
하지만 해당 코드 처럼 사용하면 제대로 작동하지 않는다.
나도 도움을 받아 알게 된것은 해당 "binding.tb.setScrollPosition(index, 0f, false)" 코드가 작동은 하지만 보여주는 화면이 더 빨라 delay를 주게된면 작동한다는 것이다.
그래서 아래 코드 처럼 쓰게 되면 작동하게 된다.
[해결코드]
private fun selectTabItem(category: String, index: Int) {
binding.tb.selectTab(binding.tb.getTabAt(index))
lifecycleScope.launch {
delay(500)
binding.tb.setScrollPosition(index, 0f, false)
}
viewModel.requestQuestion(category)
}
근데 솔직히 정확히 이해가 안되는 부분이 있다.
해당 binding.tb.setScrollPosition(index, 0f, false) 원리이다. 타고 들어가 봤지만 어떤 이유에서 정확히 보여주는 부분이 더 느린지이다.
하지만 유추할 수 있는 것은 해당 오류 코드에서는 해당 화면이 구성되기 전에 띄워지기 때문이라고 밖에 볼 수가 없다.
근데 이유가 정확한지는 모르겟다..
그래서 몇가지 돌아가는 몇가지 코드를 시험해봤다.
아래의 경우도 원하는데로 돌아간다.
[해결코드]
private fun selectTabItem(category: String, index: Int) {
lifecycleScope.launch {
binding.tb.selectTab(binding.tb.getTabAt(index))
lifecycleScope.launch(Dispatchers.Main) {
binding.tb.setScrollPosition(index, 0f, false)
}
}
viewModel.requestQuestion(category)
}
위에 코드도 가능하다.
위 코드도 가능한 것으로 보아 binding.tb.selectTab(binding.tb.getTabAt(index)) 해당 코드가 돌아가는 시점에 binding.tb.setScrollPosition(index, 0f, false)를 잡을 수 있다면 가능하다는 것이다.
하지만 그게 전체 뷰를 보여주는 것과 그정도로 차이가 나는가? 라고 봤을 때 계속 고민을 하게 만든다.
그래서 더더욱 이유가 모호해진다.
일단 원인은 해당 binding.tb.setScrollPosition(index, 0f, false) 함수가 화면을 잡기전에 뷰가 먼저 보여진다는 것 그래서 코루틴의 딜래이를 주게되면 정상적으로 보인다는 것아. 그렇다면 해당 binding.tb.selectTab(binding.tb.getTabAt(index)) 함수가 돌아간 다음 정확하게 binding.tb.setScrollPosition(index, 0f, false)함수가 돌아가는 시점에 View보다 빠르게 설정되면 가능하지 않을까? 라는 생각이 든다. 정확한가?라고 말하면 확신은 못한다.
음...
일단 해결은 됬지만 매우 찜찜한 상태이다.
일단은 코루틴에 대해서 더 공부해보도 만약에 정확한 이유를 알게 되면 해당 글을 수정하여 포스트하겠다.
추가적으로 더 좋은 방법이 있을거 같다.
'TIL > 스터디' 카테고리의 다른 글
함수 참조 (RecyclerView) 사용 (0) | 2024.04.11 |
---|---|
코틀린 함수 참조 (0) | 2024.03.29 |
LinearLayoutMananger(RecyclerView 스크롤 제어) (0) | 2024.03.27 |
ScrollView, DataBinding(하위 View 1개만) (1) | 2024.03.26 |
SavedStateHandle (0) | 2024.03.25 |