넷플릭스 같은 RecyclearView [Snap Helper]
17684 단어 RecyclerViewJavaAndroidSnapnetflix
Snapping이란?
안드로이드에서는 SnapHelper 레벨을 사용하여 RecyclearView의 Snapping을 실현할 수 있습니다.
스냅샷?스냅숏이란 굴러갈 때 보통 그렇게 플링하는 것이 아니라 특정한 물품으로 신속하게 멈추는 행위라고 생각하는 사람이 있을 것 같다.
넷플릭스의 메인 화면에는 스냅핑이 사용됐다.
Snapping 구현 방법
이번에는 안드로이드의 스냅핑을 구현하는 방법에 대해 기술한다.
RecyclearView 스크롤 State
RecyclearView 스크롤에는 세 가지 상태가 있습니다.
이번에는 안드로이드의 스냅핑을 구현하는 방법에 대해 기술한다.
RecyclearView 스크롤 State
RecyclearView 스크롤에는 세 가지 상태가 있습니다.
SCROLL_STATE_IDLE
(RecyclearView가 스크롤되지 않은 상태)SCROLL_STATE_DRAGGING
(RecyclearView가 드래그된 상태)SCROLL_STATE_SETTLING
(RecyclearView 애니메이션의 최종 위치 상태)SnapHelper
이제 이 주제의 SnapHelper 내부를 살펴보겠습니다.
SnapHelper에는 3가지 Abstract 방법이 있습니다.
여기서 Override가 의도한 Snaping을 구현할 수 있습니다.
calculateDistanceToFinalSnap
cal culateDistanceToFinal Snap은 Snap을 원하는 View(targetView)에 따라 최종 위치로 반환됩니다.
/**
* Override this method to snap to a particular point within the target view or the container
* view on any axis.
* <p>
* This method is called when the {@link SnapHelper} has intercepted a fling and it needs
* to know the exact distance required to scroll by in order to snap to the target view.
*
* @param layoutManager the {@link RecyclerView.LayoutManager} associated with the attached
* {@link RecyclerView}
* @param targetView the target view that is chosen as the view to snap
*
* @return the output coordinates the put the result into. out[0] is the distance
* on horizontal axis and out[1] is the distance on vertical axis.
*/
@SuppressWarnings("WeakerAccess")
@Nullable
public abstract int[] calculateDistanceToFinalSnap(@NonNull LayoutManager layoutManager, @NonNull View targetView);
targetView 빨리 찍고 싶은 View.위의 넷플릭스와 같은 행동을 실현하기 위해 targetView를 중심으로 스냅 처리를 했고, targetView의 중심과 RecyclearView 자체 중심 위치의 차이만 돌려주면 된다.
@Override
int[] calculateDistanceToFinalSnap(@NonNull RecyclerView.LayoutManager layoutManager, @NonNull View targetView) {
int[] out = new int[2];
if (layoutManager.canScrollHorizontally()) {
out[0] = getDistance(layoutManager, targetView, OrientationHelper.createHorizontalHelper(layoutManager));
} else {
out[0] = 0;
}
if (layoutManager.canScrollVertically()) {
out[1] = getDistance(layoutManager, targetView, OrientationHelper.createVerticalHelper(layoutManager));
} else {
out[1] = 0;
}
return out;
}
int getDistance(RecyclerView.LayoutManager layoutManager, View targetView, OrientationHelper helper) {
final int childCenter = helper.getDecoratedStart(targetView) + (helper.getDecoratedMeasurement(targetView) / 2);
final int containerCenter = layoutManager.getClipToPadding()
? helper.getStartAfterPadding() + helper.getTotalSpace() / 2
: helper.getEnd() / 2;
return childCenter - containerCenter;
}
findSnapView
findSnapview에서 Snap을 원하는 View를 이름별로 반환합니다.여기서 반환된 View는 위의 cal culateDistanceToFinalsnap 매개 변수로 들어갑니다.
이 방법은 스크롤 상태
SCROLL_STATE_IDLE
와 SnapHelper가 RecyclearView에서 Attach라고 부른다.
/**
* Override this method to provide a particular target view for snapping.
* <p>
* This method is called when the {@link SnapHelper} is ready to start snapping and requires
* a target view to snap to. It will be explicitly called when the scroll state becomes idle
* after a scroll. It will also be called when the {@link SnapHelper} is preparing to snap
* after a fling and requires a reference view from the current set of child views.
* <p>
* If this method returns {@code null}, SnapHelper will not snap to any view.
*
* @param layoutManager the {@link RecyclerView.LayoutManager} associated with the attached
* {@link RecyclerView}
*
* @return the target view to which to snap on fling or end of scroll
*/
@SuppressWarnings("WeakerAccess")
@Nullable
public abstract View findSnapView(LayoutManager layoutManager);
위의 넷플릭스와 같은 행동을 실현하기 위해 3개의 item이 함께 굴러가기 때문에 item의position은 1, 4, 7...그리고 센터에 가장 가까운view를 돌려주시면 됩니다.
@Override
View findSnapView(RecyclerView.LayoutManager layoutManager) {
OrientationHelper helper = layoutManager.canScrollHorizontally()
? OrientationHelper.createHorizontalHelper(layoutManager)
: OrientationHelper.createVerticalHelper(layoutManager);
int childCount = layoutManager.getChildCount();
View closestChild = null;
int containerCenter = layoutManager.getClipToPadding()
? helper.getStartAfterPadding() + helper.getTotalSpace() / 2
: helper.getEnd() / 2;
int absClosest = Integer.MAX_VALUE;
for (int i = 0; i < childCount; i++) {
final View child = layoutManager.getChildAt(i);
if (child == null) continue;
if (getChildPosition(child, helper) % 3 != 1) continue;
int childCenter = helper.getDecoratedStart(child) + (helper.getDecoratedMeasurement(child) / 2);
int absDistance = Math.abs(childCenter - containerCenter);
if (absDistance < absClosest) {
absClosest = absDistance;
closestChild = child;
}
}
return closestChild;
}
findTargetSnapPosition
findTargetSnapPosition에서 targetView의 Position을 반환합니다.언뜻 보기에는findSnapview와 별 차이가 없지만 방법의 호출 시기는 다르다.
findTarget SnapPosition은 RecyclearView가
SCROLL_STATE_SETTLING
로 변한 상태에서 불린다.따라서 View 자체는 생성되지 않을 수 있으므로 View가 아닌 View의 Position입니다./**
* Override to provide a particular adapter target position for snapping.
*
* @param layoutManager the {@link RecyclerView.LayoutManager} associated with the attached
* {@link RecyclerView}
* @param velocityX fling velocity on the horizontal axis
* @param velocityY fling velocity on the vertical axis
*
* @return the target adapter position to you want to snap or {@link RecyclerView#NO_POSITION}
* if no snapping should happen
*/
public abstract int findTargetSnapPosition(LayoutManager layoutManager, int velocityX, int velocityY);
넷플릭스와 같은 동작을 수행하려면 스크롤 방향에 따라 잡은 View의 Positionw를 반환합니다.
@Override
int findTargetSnapPosition(RecyclerView.LayoutManager layoutManager, int velocityX, int velocityY) {
boolean forwardDirection = layoutManager.canScrollHorizontally() ? velocityX > 0 : velocityY > 0;
return forwardDirection ? previousClosestPosition + 3 : previousClosestPosition - 3;
}
previousCloset Position에는 findSnapview가 없으며 마지막 Snap의 Position을 구성원 변수 등에 저장하면 됩니다.최후
SnapHelper의 사용법을 상세히 썼지만, 이번에 쓴 내용을 대량으로 사용해 프로그램 라이브러리를 만들었다!
Snap 방향Gravity
과 스크롤할 item 수SnapCount
를 지정할 수 있습니다.
꼭 보셔야 한다면 정말 감사합니다.
그리고 괜찮은 사람이 꼭 스타가 된다면 고마워요!
feature1: Gravity
feature2: SnapCount
Reference
이 문제에 관하여(넷플릭스 같은 RecyclearView [Snap Helper]), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다
https://qiita.com/takusemba/items/9df28c8d30129e1f4ac2
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념
(Collection and Share based on the CC Protocol.)
Reference
이 문제에 관하여(넷플릭스 같은 RecyclearView [Snap Helper]), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://qiita.com/takusemba/items/9df28c8d30129e1f4ac2텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)