[문제 상황]
1. 세로 리사이클러 리스트 뷰 + 가로 리사이클러 뷰(View Pager)
2. 세로 스크롤뷰 + 가로 리사이클러 리스트 뷰
3. 세로 스크롤 바텀시트 + 가로 리사이클러뷰(View Pager)
가로, 세로 스크롤이 중첩되면서 원하지 않는 액션이 되는 경우가 생김
즉 가로 슬라이드를 하는데, 세로가 스크롤 되는 문제가 발생함ㅜ_ㅜ
[조치 방향]
사람이 손가락으로 가로 슬라이드 하다보면 y축에 수평으로만 슬라이드 하진 않더군요ㅋㅋ
사선방향으로, 대각선으로 슬라이드 하다보니 이정도 대각선까지는 가로슬라이드로 먹었으면 좋겠다 싶더라고요
구글링하다보니 선행해서 고민하신분들이 있었고, 조치방법도 찾을 수 있었습니다.
가로스크롤을 하면 자식이 먹게 하자. 근데 buffer를 세로스크롤 일지라도, buffer만큼 가로스크롤을 더 먹게 하자.
/**
* recyclerView를 가로 스크롤시 부모 리사이클러뷰가 세로로 스크롤 되는 현상을 줄이기 위해 사용하고 있음.
* ybuffer가 클수록 부모 리사이클러뷰가 세로 스크롤 먹지 되지 않게 된다.
*/
class RecyclerViewGestureListener(val recyclerView: RecyclerView,yBuffer:Int =10) : GestureDetector.SimpleOnGestureListener() { private val Y_BUFFER = yBuffer
override fun onScroll(
e1: MotionEvent,
e2: MotionEvent,
distanceX: Float,
distanceY: Float
): Boolean {
if (abs(distanceX) >abs(distanceY)) {
//onScroll true
// Detected a horizontal scroll, disallow the recyclerview interceptor
recyclerView.parent.requestDisallowInterceptTouchEvent(true)
} else if (abs(distanceY) > Y_BUFFER) {
// Detected a vertical scroll, allow the recyclerview interceptor
//onScroll false
recyclerView.parent.requestDisallowInterceptTouchEvent(false)
}
return super.onScroll(e1,e2,distanceX,distanceY)
}
override fun onDown(e: MotionEvent): Boolean {
// Prevent ViewPager from intercepting touch events as soon as a DOWN is detected.
// If we don't do this the next MOVE event may trigger the ViewPager to switch
// tabs before this view can intercept the event.
//onDown true
recyclerView.parent.requestDisallowInterceptTouchEvent(true)
return super.onDown(e)
}
}
스크롤시 x와 y를 비교해서 가로 스크롤이 될 것인지 세로스크롤 먹게 할 것인지, 부모의 리사이클러뷰에 스크롤 이벤트를 전달할지를 설정해주도록 했습니다.
비슷한 케이스가 여러번 발생하길래 아래 처럼 RecyclerView의 확장 함수를 만들어서 자식리사이클러 뷰(가로스크롤)에 제스쳐 리스너를 설정해서 사용했습니다.
fun RecyclerView.setScrollSensitivity(yBuffer:Int = 10) {
val gestureDetector
= GestureDetector(this.context, RecyclerViewGestureListener(this, yBuffer))
this.addOnItemTouchListener(
object: RecyclerView.OnItemTouchListener{
override fun onInterceptTouchEvent(rv: RecyclerView, e: MotionEvent): Boolean {
gestureDetector.onTouchEvent(e)
return false
}
override fun onTouchEvent(rv: RecyclerView, e: MotionEvent) {
}
override fun onRequestDisallowInterceptTouchEvent(disallowIntercept: Boolean) {
}
}
)
}
10~30 정도의 버퍼를 줘서 사용하니깐 좀 더 단단하게 고정된 세로리스트 느낌을 받을 수 있엇고, 가로 스크롤하기가 수월해졌습니다.
[참고]
https://medium.com/mobile-app-development-publication/understanding-android-touch-flow-control-bcc413e6a57e
https://stackoverflow.com/questions/38466413/disable-viewpager-paging-when-child-recyclerview-scrolls-to-last-item
https://localcoder.org/vertical-viewpager2-with-recyclerview-scrolling-issue
'SW Programming > Android' 카테고리의 다른 글
[안드로이드] 카드뷰, 무한로딩, View pager transformation (0) | 2022.08.18 |
---|---|
sonarLint / Android의 코루틴 권장사항 (0) | 2022.08.08 |
Android 단말에서 온갖 이벤트를 모니터링, 제어하고 싶다. adb shell getevent (0) | 2021.03.23 |
IOS 안드로이드 스튜디오 업데이트 오류 해결 (0) | 2017.06.15 |
리사이클러 뷰 RecyclerView 정리 (0) | 2017.04.26 |
댓글