RecyclearView 장거리 스크롤

9406 단어 Android

TL;DR

  • RecyclearView의 smoth scroller를 변경하기 위해 Smooth Scroller를 설치
  • 전부 자기가 하기는 어려울 것 같지만 기존의 확장만으로도 동작을 변경할 수 있다
  • 개시하다


    제목이 뭐냐, 이 어떤 상태냐에 따라 이동 거리가 길어지는 위치RecyclerView#smoothScrollToPosition에서는 아래 Gif 애니메이션처럼 일정한 속도로 계속 움직이는 동작이다.

    트위터 공식 클라이언트에서는 태그를 클릭하면 TL의 시작으로 돌아갈 수 있지만, 이동 거리가 길어지면 smooth scroll이 필요 없어 순식간에 시작이 나온다.
    이런 동작도 괜찮은데 너무 지루해서 살짝 굴린 뒤 지정된 위치로 이동하는 동작을 실현하기 위해 몇 가지 조사를 하고 정리했다.

    RecyclearView에 smoth scroll을 진행하게 한 사람은 누구입니까?

    LinearLayoutManager#smoothScrollToPosition의 설치를 보세요.
    @Override
    public void smoothScrollToPosition(RecyclerView recyclerView, RecyclerView.State state,
            int position) {
        LinearSmoothScroller linearSmoothScroller =
                new LinearSmoothScroller(recyclerView.getContext());
        linearSmoothScroller.setTargetPosition(position);
        startSmoothScroll(linearSmoothScroller);
    }
    
    생성LinearSmoothScroller 이 녀석의 실례를 startSmoothScroll에 맡겼을 뿐이다.
    이 녀석이 바로 스mothScroll의 정체라는 얘기다.LinearLayoutManagerGridLayoutManager에서 이LinearSmoothScroller를 사용했지만 엄밀히 말하면 RecyclerView#SmoothScroller의 abstract class만 계승하면 된다.
  • LinearSmoothScroller
  • SmoothScroller (RecyclerView.java#L10916-L11346))
  • 장거리 이동 동작


    실제로 RecyclearView의 내부 움직임을 추적하려면 얼마가 지나도 도착할 수 없기 때문에 적절한 곳에 인상 파일럿을 붙여 조사한다.
    따라서 updateActionForInterimTarget 이런 방법으로 이동 거리와 시간 등을 계산하지만 지정된 위치에 이르지 못하면 도착할 때까지 반복적으로 부른다.
    따라서 이 녀석을 updateActionForInterimTarget의 두 번째 호출로 확장하고 smothScroll을 멈추고 지정된 위치로 이동해 보자.

    Smooth scroll 작업 사용자 정의


    갑작스럽지만 코드예요.
    class OneTimeSmoothScroller(recyclerView: RecyclerView) : LinearSmoothScroller(recyclerView.context) {
    
        private var isScrolled: Boolean = false
    
        override fun updateActionForInterimTarget(action: Action) {
            if (isScrolled) {
                // 2回目は一気に指定位置までジャンプ
                action.jumpTo(targetPosition)
            } else {
                // 1回目は通常通りにスクロール
                super.updateActionForInterimTarget(action)
                isScrolled = true
            }
        }
    }
    
    그게 다야.동작을 실제로 보다.

    예상한 동작을 의외로 해냈지만 스크롤 속도가 고정돼 있어 약간 갑작스러운 점프 느낌이 든다.
    그래서 약간의 변경이 더해졌다.LinearSmoothScroller의 실시 방식을 보면updateActionForInterimTarget의 마지막 부분은 다음과 같다.
    action.update((int) (mInterimTargetDx * TARGET_SEEK_EXTRA_SCROLL_RATIO)
            , (int) (mInterimTargetDy * TARGET_SEEK_EXTRA_SCROLL_RATIO)
            , (int) (time * TARGET_SEEK_EXTRA_SCROLL_RATIO), mLinearInterpolator);
    
    어쨌든
  • 값을 매개 변수로 전달하는 action로 설정하면 smooth scroll 애니메이션에 반영됩니다
  • 애니메이션 사용LinearInterpolator
  • 닮았어.
    당돌함을 조금이나마 완화시키기 위해LinearInterpolatorAccelerateInterpolator로바꿔보자.
    class OneTimeSmoothScroller(recyclerView: RecyclerView) : LinearSmoothScroller(recyclerView.context) {
        private var isScrolled: Boolean = false
    
        override fun updateActionForInterimTarget(action: Action) {
            if (isScrolled) {
                action.jumpTo(targetPosition)
            } else {
                super.updateActionForInterimTarget(action)
                action.duration *= 2  // 動きが分かりやすいよう時間を2倍にする
                action.interpolator = AccelerateInterpolator(1.5F)
                isScrolled = true
            }
        }
    }
    
    실제 동작은 바로 이런 느낌이다.

    Gif 애니메이션은 이해하기 어렵지만 약간 당돌한 느낌이 든다.

    etc


    조금만 변경action하면 구조를 바꿀 수 있지만 dxdy는 쉽게 변경하지 않는 것이 좋다.
    이번 예라면 도착한 거리를 계산할 때 지정한 위치에서 스크롤이 멈추지 않는다.
    샘플 코드 여기 있습니다https://github.com/chibatching/long-distance-smooth-scroll-sample

    좋은 웹페이지 즐겨찾기