… mScroller.startScroll(getScrollX(), 0, delta, 0, Math.abs(delta) * 2); … @Override public void computeScroll() { Log.d(TAG, "getCurrX() = " + mScroller.getCurrX()); Log.d(TAG, "getCurrY() = " + mScroller.getCurrY()); if (mScroller.computeScrollOffset()) { if (mScroller.isFinished()) { Log.d("namh", "mScroller is finished"); if(mState == SIDEBAR_OPEN){ mState = SIDEBAR_CLOSE; }else{ mState = SIDEBAR_OPEN; } // make a layout requestLayout(); invalidate(); } else { /** * * * Unless, {@link #scrollTo} is not called here, * The View works like the one big page, so that * the fling works just like the non-elastic drag. * */ Log.d(TAG, "X = "+mScroller.getCurrX()); // invalidate() is not needed after this function. // because the view will be invalidated in the {@link #scrollTo} scrollTo(mScroller.getCurrX(), mScroller.getCurrY()); invalidate(); } } }
기본적으로 이 녀석은 빈 함수 이기 때문에 override 할 때 굳이 super.computeScroll() 을 호출할 필요는 없다.
이 코드를 보면서 이게 어떻게 동작하는지 분석하고 있었다. 그런데, 처음에 scrollTo(x, y) 가 뜻하는 바가 "x, y 지점으로 scroll 해라" 이기 때문에, scroll 이 끝나고 난 후에 computeScroll() 이 더 이상 호출되지 않을 것이라고 생각했다.
근데 이 녀석(computeScroll())은 일단 ViewGroup 에서 scrolling 을 하고 있을 때 호출되는 녀석이 아니라 draw() 할 때 호출되는 녀석이다.
scrollTo() 를 통해서 특정지점까지 움직이라고 하고, 특정지점에 도착한 모습을 그리면서 draw() 가 호출되는데 그러면서 computeScroll() 이 호출된다.
그렇기 때문에 위의 코드에서 computeScroll() 에서 scrollTo() 를 호출하면, scrollTo() 가 끝나는 시점에 computeScroll() 이 한 번 더 호출된다. 참고로, computeScroll() 은 scrollTo() 와 관련해서 호출되는 invalidate() 에 의해서 화면이 다시 그려지면서 호출되는 듯 하다.(추측)
그래서 이 때 다시 scrollTo() 를 호출해서 좀 더 그리고 다시 computeScroll() 로 돌아오고, 이런 식으로 scroll 이 목적지에 다다를 때까지(mScroller.computeScrollOffset() == false) loop 를 돈다고 보면 되겠다.
이 때 잠시 오해를 한 부분이
mScroller.startScroll();를 통해 설정해 놓은 목표지점이 scrollTo() 로 인해 바뀌어 버린다고 생각했는데, Scroll() 과 View() 는 다른 object 여서 그럴 일은 없으니까 오해하지 말자.
scrollTo() 이후에 invalidate()
위의 같은 코드를 가지고 emulator 에서는 큰 문제가 없었는데, duration 을 길게 잡고 폰에서 테스트를 할 때는 mScroller.getCurrX() 와 getScrollX() 값이 같은 경우가 발생했다. 두값이 같으면 scrollTo() 는 그냥 return 하게 되어있기 때문에 화면이 다시 그려지지 않게 된다. 그래서 scroll 이 되지않고 drag 한채로 정지한 화면이 된다.확실히 언제 getCurrX() 와 getScrollX() 가 같아지는지에 대해서는 잘 모르겠지만, animation 의 끝부분에 갈수록 그렇게 되는 듯 하다. (추측컨데, 값이 int 여서 float 이라면 같은 값이 아닌 경우에도 같은 값이 나오는 경우가 발생하지 않을까 생각한다.)
그런데 문제는 mScroller.computeScrollOffset()이 true 이기 때문에 아직 animation 이 끝나지 않은 상태인데도 getCurrX() 와 getScrollX() 값이 같아서 scrollTo() 가 아무런 동작도 하지 않아 화면이 그려지다 만 상태로 보이는 듯 하다.
이런 이유로 scrollTo() 에서 invalidate() 를 호출하지 않는 경우에 대비해서 scrollTo() 이후에 명시적으로 invalidate() 를 호출해 주는 것이 정상적인 작동에 도움을 준다.
댓글 없음:
댓글 쓰기