Horizontal, Vertical 방향이 혼재된 Nested RecyclerView를 구현하다 보면
세로 스크롤을 하는 도중 가로 스크롤로 넘어가는데 자연스럽지 않거나 그 반대 상황이 생긴다.
그럴때 기본 RecyclerView 대신 아래의 커스텀 RecyclerView를 사용하면 조금 더 자연스러워 진다.
간단하게 주석으로 무슨일을 하는지 적어두었다.
원 코드 출처는 여기이다.
public class OrientationAwareRecyclerView extends RecyclerView {
private float lastX = 0.0f;
private float lastY = 0.0f;
private boolean scrolling = false;
public OrientationAwareRecyclerView(@NonNull Context context) {
this(context, null);
}
public OrientationAwareRecyclerView(@NonNull Context context, @Nullable AttributeSet attrs) {
this(context, attrs, 0);
}
public OrientationAwareRecyclerView(@NonNull Context context, @Nullable AttributeSet attrs,
int defStyleAttr) {
super(context, attrs, defStyleAttr);
addOnScrollListener(new OnScrollListener() {
@Override
public void onScrollStateChanged(@NonNull RecyclerView recyclerView, int newState) {
super.onScrollStateChanged(recyclerView, newState);
scrolling = newState != RecyclerView.SCROLL_STATE_IDLE;
}
});
}
@Override
public boolean onInterceptTouchEvent(MotionEvent e) {
final LayoutManager lm = getLayoutManager();
if (lm == null) {
return super.onInterceptTouchEvent(e);
}
boolean allowScroll = true;
switch (e.getActionMasked()) {
case MotionEvent.ACTION_DOWN: {
lastX = e.getX();
lastY = e.getY();
// If we were scrolling, stop now by faking a touch release
// 아마 Fling시에 손가락 터치로 멈추는거일듯...
if (scrolling) {
MotionEvent newEvent = MotionEvent.obtain(e);
newEvent.setAction(MotionEvent.ACTION_UP);
return super.onInterceptTouchEvent(newEvent);
}
break;
}
case MotionEvent.ACTION_MOVE: {
// We're moving, so check if we're trying
// to scroll vertically or horizontally so we don't intercept the wrong event.
float currentX = e.getX();
float currentY = e.getY();
float dx = Math.abs(currentX - lastX);
float dy = Math.abs(currentY - lastY);
// 세로로 스크롤 할려고할경우 lm 이 세로 스크롤 가능한지 여부, 가로로 할경우 가로 스크롤 가능여부에 따름.
// 만약 가로로 스크롤 하지 못하는 rv인데 가로로 스크롤 하려고 할 경우 Touch Event를 가로채는걸 막는다.
allowScroll = dy > dx ? lm.canScrollVertically() : lm.canScrollHorizontally();
break;
}
}
if (!allowScroll) {
return false;
}
return super.onInterceptTouchEvent(e);
}
}
'프로그래밍 > Android' 카테고리의 다른 글
[안드로이드] WebView에서 세션 쿠키 활성화 하기 (소셜 로그인) (3) | 2021.03.14 |
---|---|
[안드로이드] Context 사용 범위 정리 (0) | 2021.03.12 |
[안드로이드] 에뮬레이터 감지 하는 법 (Detecting Emulator Device) (1) | 2021.03.08 |
[안드로이드] RecyclerView를 잘 사용하기 위한 팁들. (0) | 2021.02.05 |
[안드로이드] 예제로 알아보는 바인드된 서비스 (Bound Service) (0) | 2021.01.18 |