|
@@ -3,6 +3,7 @@ package kr.co.zumo.app.lifeplus.view.screen.main;
|
|
|
import android.graphics.PointF;
|
|
import android.graphics.PointF;
|
|
|
import android.support.annotation.NonNull;
|
|
import android.support.annotation.NonNull;
|
|
|
import android.support.annotation.Nullable;
|
|
import android.support.annotation.Nullable;
|
|
|
|
|
+import android.support.v7.widget.LinearLayoutManager;
|
|
|
import android.support.v7.widget.LinearSmoothScroller;
|
|
import android.support.v7.widget.LinearSmoothScroller;
|
|
|
import android.support.v7.widget.OrientationHelper;
|
|
import android.support.v7.widget.OrientationHelper;
|
|
|
import android.support.v7.widget.RecyclerView;
|
|
import android.support.v7.widget.RecyclerView;
|
|
@@ -11,6 +12,7 @@ import android.support.v7.widget.RecyclerView.SmoothScroller;
|
|
|
import android.support.v7.widget.RecyclerView.SmoothScroller.ScrollVectorProvider;
|
|
import android.support.v7.widget.RecyclerView.SmoothScroller.ScrollVectorProvider;
|
|
|
import android.support.v7.widget.SnapHelper;
|
|
import android.support.v7.widget.SnapHelper;
|
|
|
import android.util.DisplayMetrics;
|
|
import android.util.DisplayMetrics;
|
|
|
|
|
+import android.util.Log;
|
|
|
import android.view.View;
|
|
import android.view.View;
|
|
|
import android.view.animation.DecelerateInterpolator;
|
|
import android.view.animation.DecelerateInterpolator;
|
|
|
import android.widget.Scroller;
|
|
import android.widget.Scroller;
|
|
@@ -222,12 +224,20 @@ public class MainCategorySnapper extends RecyclerView.OnFlingListener {
|
|
|
return;
|
|
return;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+// int[] snapDistance = calculateDistanceToFinalSnap(layoutManager, snapView);
|
|
|
|
|
+// snapDistance[0] -= snapOffset; // 마지막 뷰일 경우 snapOffset 을 적용하면 부자연스럽게 스크롤 됨
|
|
|
|
|
+// snapDistance[1] -= snapOffset;
|
|
|
|
|
+// if (snapDistance[0] != 0 || snapDistance[1] != 0) {
|
|
|
|
|
+// mRecyclerView.smoothScrollBy(snapDistance[0], snapDistance[1], new DecelerateInterpolator());
|
|
|
|
|
+// }
|
|
|
|
|
+
|
|
|
/**
|
|
/**
|
|
|
* 현재 스크롤 포지션에 가장 가까운 뷰로 스크롤 시킨다.
|
|
* 현재 스크롤 포지션에 가장 가까운 뷰로 스크롤 시킨다.
|
|
|
* - recyclerView 의 스크롤을 이용하지않고 직접 스크롤시킨다.
|
|
* - recyclerView 의 스크롤을 이용하지않고 직접 스크롤시킨다.
|
|
|
* - recyclerView 는 너무 빠름.
|
|
* - recyclerView 는 너무 빠름.
|
|
|
*/
|
|
*/
|
|
|
int position = layoutManager.getPosition(snapView);
|
|
int position = layoutManager.getPosition(snapView);
|
|
|
|
|
+ Log.i("APP# MainCategorySnapper | snapToTargetExistingView", "|" + "position: " + position);
|
|
|
|
|
|
|
|
SmoothScroller smoothScroller = createScroller(layoutManager);
|
|
SmoothScroller smoothScroller = createScroller(layoutManager);
|
|
|
if (smoothScroller == null) {
|
|
if (smoothScroller == null) {
|
|
@@ -271,9 +281,46 @@ public class MainCategorySnapper extends RecyclerView.OnFlingListener {
|
|
|
// The associated RecyclerView has been removed so there is no action to take.
|
|
// The associated RecyclerView has been removed so there is no action to take.
|
|
|
return;
|
|
return;
|
|
|
}
|
|
}
|
|
|
|
|
+ int offset = snapOffset;
|
|
|
|
|
+ if (mRecyclerView.getChildAdapterPosition(targetView) == (mRecyclerView.getAdapter().getItemCount() - 1)) {
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 보통 뷰일 때 스크롤 타겟 위치
|
|
|
|
|
+ * - 0 + offset
|
|
|
|
|
+ *
|
|
|
|
|
+ * 마지막 뷰일 때
|
|
|
|
|
+ * => offset = screenWidth - 마지막 뷰 사이즈
|
|
|
|
|
+ */
|
|
|
|
|
+ OrientationHelper helper = getOrientationHelper(layoutManager);
|
|
|
|
|
+ if (null != helper) {
|
|
|
|
|
+ offset = (layoutManager.getWidth() - helper.getDecoratedMeasurement(targetView));
|
|
|
|
|
+ }
|
|
|
|
|
+// Log.e("APP# MainCategorySnapper | onTargetFound", "|" + "layoutManager.getWidth(): " + layoutManager.getWidth());
|
|
|
|
|
+// Log.e("APP# MainCategorySnapper | onTargetFound", "|" + "helper.getDecoratedMeasurement(targetView): " + helper.getDecoratedMeasurement(targetView));
|
|
|
|
|
+// Log.e("APP# MainCategorySnapper | onTargetFound", "|" + "offset: " + offset);
|
|
|
|
|
+ }
|
|
|
int[] snapDistances = calculateDistanceToFinalSnap(mRecyclerView.getLayoutManager(), targetView);
|
|
int[] snapDistances = calculateDistanceToFinalSnap(mRecyclerView.getLayoutManager(), targetView);
|
|
|
- final int dx = snapDistances[0] - snapOffset;
|
|
|
|
|
- final int dy = snapDistances[1] - snapOffset;
|
|
|
|
|
|
|
+ final int dx;
|
|
|
|
|
+ final int dy;
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 방향을 고려해서 offset 적용한다. 항상 적용하면 긴쪽을 기준으로 time 이 계산되어서 이동 거리가 0일 경우 느리게 움직일 수 있다.
|
|
|
|
|
+ */
|
|
|
|
|
+ LinearLayoutManager linearLayoutManager = (LinearLayoutManager) layoutManager;
|
|
|
|
|
+ if (null != linearLayoutManager) {
|
|
|
|
|
+ if (linearLayoutManager.getOrientation() == LinearLayoutManager.HORIZONTAL) {
|
|
|
|
|
+ dx = snapDistances[0] - offset;
|
|
|
|
|
+ dy = snapDistances[1];
|
|
|
|
|
+ }
|
|
|
|
|
+ else {
|
|
|
|
|
+ dx = snapDistances[0];
|
|
|
|
|
+ dy = snapDistances[1] - offset;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ else {
|
|
|
|
|
+ dx = snapDistances[0];
|
|
|
|
|
+ dy = snapDistances[1];
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
final int time = calculateTimeForDeceleration(Math.max(Math.abs(dx), Math.abs(dy)));
|
|
final int time = calculateTimeForDeceleration(Math.max(Math.abs(dx), Math.abs(dy)));
|
|
|
if (time > 0) {
|
|
if (time > 0) {
|
|
|
int newTime = Math.min(TIME_MAX, Math.max(time, TIME_MIN));
|
|
int newTime = Math.min(TIME_MAX, Math.max(time, TIME_MIN));
|
|
@@ -288,6 +335,16 @@ public class MainCategorySnapper extends RecyclerView.OnFlingListener {
|
|
|
};
|
|
};
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ private OrientationHelper getOrientationHelper(LayoutManager layoutManager) {
|
|
|
|
|
+ if (layoutManager.canScrollVertically()) {
|
|
|
|
|
+ return getVerticalHelper(layoutManager);
|
|
|
|
|
+ }
|
|
|
|
|
+ else if (layoutManager.canScrollHorizontally()) {
|
|
|
|
|
+ return getHorizontalHelper(layoutManager);
|
|
|
|
|
+ }
|
|
|
|
|
+ return null;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
/**
|
|
/**
|
|
|
* Override this method to snap to a particular point within the target view or the container
|
|
* Override this method to snap to a particular point within the target view or the container
|
|
|
* view on any axis.
|
|
* view on any axis.
|
|
@@ -338,11 +395,9 @@ public class MainCategorySnapper extends RecyclerView.OnFlingListener {
|
|
|
@SuppressWarnings("WeakerAccess")
|
|
@SuppressWarnings("WeakerAccess")
|
|
|
@Nullable
|
|
@Nullable
|
|
|
public View findSnapView(LayoutManager layoutManager) {
|
|
public View findSnapView(LayoutManager layoutManager) {
|
|
|
- if (layoutManager.canScrollVertically()) {
|
|
|
|
|
- return findTopView(layoutManager, getVerticalHelper(layoutManager));
|
|
|
|
|
- }
|
|
|
|
|
- else if (layoutManager.canScrollHorizontally()) {
|
|
|
|
|
- return findTopView(layoutManager, getHorizontalHelper(layoutManager));
|
|
|
|
|
|
|
+ OrientationHelper helper = getOrientationHelper(layoutManager);
|
|
|
|
|
+ if (null != helper) {
|
|
|
|
|
+ return findTopView(layoutManager, helper);
|
|
|
}
|
|
}
|
|
|
return null;
|
|
return null;
|
|
|
}
|
|
}
|
|
@@ -372,13 +427,14 @@ public class MainCategorySnapper extends RecyclerView.OnFlingListener {
|
|
|
}
|
|
}
|
|
|
int absClosest = Integer.MAX_VALUE;
|
|
int absClosest = Integer.MAX_VALUE;
|
|
|
|
|
|
|
|
- int childMaxSize = 0;
|
|
|
|
|
|
|
+ int secondItemPositionMax = 0;
|
|
|
|
|
|
|
|
for (int i = 0; i < childCount; ++i) {
|
|
for (int i = 0; i < childCount; ++i) {
|
|
|
final View child = layoutManager.getChildAt(i);
|
|
final View child = layoutManager.getChildAt(i);
|
|
|
int childStart = helper.getDecoratedStart(child);
|
|
int childStart = helper.getDecoratedStart(child);
|
|
|
int childEnd = helper.getDecoratedEnd(child);
|
|
int childEnd = helper.getDecoratedEnd(child);
|
|
|
- int childSize = Math.abs(childEnd - childStart) + snapOffset;
|
|
|
|
|
|
|
+ int childSize = Math.abs(childEnd - childStart);
|
|
|
|
|
+ int secondItemPosition = childSize + snapOffset;
|
|
|
int childCenter = childStart + (helper.getDecoratedMeasurement(child) >> 2);
|
|
int childCenter = childStart + (helper.getDecoratedMeasurement(child) >> 2);
|
|
|
int absDistance = Math.abs(childCenter - (top + (childSize >> 2)));
|
|
int absDistance = Math.abs(childCenter - (top + (childSize >> 2)));
|
|
|
|
|
|
|
@@ -388,21 +444,22 @@ public class MainCategorySnapper extends RecyclerView.OnFlingListener {
|
|
|
closestChild = child;
|
|
closestChild = child;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- if (childMaxSize < childSize) {
|
|
|
|
|
- childMaxSize = childSize;
|
|
|
|
|
|
|
+ if (secondItemPositionMax < secondItemPosition) {
|
|
|
|
|
+ secondItemPositionMax = secondItemPosition;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
/**
|
|
|
* 마지막이 기준 위치보다 왼쪽에 있으면 녀석을 타겟으로 본다.
|
|
* 마지막이 기준 위치보다 왼쪽에 있으면 녀석을 타겟으로 본다.
|
|
|
* - 마지막 녀석은 크기가 작아서 그걸로 확인
|
|
* - 마지막 녀석은 크기가 작아서 그걸로 확인
|
|
|
*/
|
|
*/
|
|
|
- if (childMaxSize > childSize) {
|
|
|
|
|
|
|
+ if (secondItemPositionMax > childSize) {
|
|
|
// padding start + childSize > lastChild.x
|
|
// padding start + childSize > lastChild.x
|
|
|
// Log.w("APP# MainCategorySnapper | findTopView", "|" + "padding: " + helper.getStartAfterPadding());
|
|
// Log.w("APP# MainCategorySnapper | findTopView", "|" + "padding: " + helper.getStartAfterPadding());
|
|
|
-// Log.w("APP# MainCategorySnapper | findTopView", "|" + "childMaxSize: " + childMaxSize);
|
|
|
|
|
|
|
+// Log.w("APP# MainCategorySnapper | findTopView", "|" + "secondItemPositionMax: " + secondItemPositionMax);
|
|
|
|
|
+// Log.w("APP# MainCategorySnapper | findTopView", "|" + "secondItemPosition: " + secondItemPosition);
|
|
|
// Log.w("APP# MainCategorySnapper | findTopView", "|" + "snapOffset: " + snapOffset);
|
|
// Log.w("APP# MainCategorySnapper | findTopView", "|" + "snapOffset: " + snapOffset);
|
|
|
// Log.w("APP# MainCategorySnapper | findTopView", "|" + "child.x: " + child.getX());
|
|
// Log.w("APP# MainCategorySnapper | findTopView", "|" + "child.x: " + child.getX());
|
|
|
- if (childMaxSize > child.getX()) {
|
|
|
|
|
|
|
+ if (secondItemPositionMax - (childSize >> 1) > child.getX()) {
|
|
|
closestChild = child;
|
|
closestChild = child;
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|