Fix snap helper

This commit is contained in:
mvp76 2016-11-23 12:37:06 +01:00
parent d02ea05865
commit b36e581480

View File

@ -1,5 +1,6 @@
package org.fdroid.fdroid.views;
import android.support.annotation.NonNull;
import android.support.v4.view.ViewCompat;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.LinearSnapHelper;
@ -11,6 +12,9 @@ import static android.support.v7.widget.RecyclerView.NO_POSITION;
public class LinearLayoutManagerSnapHelper extends LinearSnapHelper {
private View mLastSavedTarget;
private int mLastSavedDistance;
public interface LinearSnapHelperListener {
/**
* Tells the listener that we have selected a view to snap to.
@ -36,29 +40,56 @@ public class LinearLayoutManagerSnapHelper extends LinearSnapHelper {
@Override
public View findSnapView(RecyclerView.LayoutManager layoutManager) {
View snappedView = super.findSnapView(layoutManager);
if (layoutManager.canScrollHorizontally()) {
if (snappedView != null && layoutManager.canScrollHorizontally()) {
if (layoutManager instanceof LinearLayoutManager) {
mLastSavedTarget = null;
int distSnap = super.calculateDistanceToFinalSnap(layoutManager, snappedView)[0];
int firstChild = ((LinearLayoutManager) layoutManager).findFirstVisibleItemPosition();
int lastChild = ((LinearLayoutManager) layoutManager).findLastVisibleItemPosition();
if (firstChild == 0) {
View child = layoutManager.findViewByPosition(firstChild);
if (mOrientationHelper.getDecoratedEnd(child) >= mOrientationHelper.getDecoratedMeasurement(child) / 2
&& mOrientationHelper.getDecoratedEnd(child) > 0) {
int dist1 = super.calculateDistanceToFinalSnap(layoutManager, snappedView)[0];
int dist2 = mOrientationHelper.getDecoratedStart(child);
if (Math.abs(dist1) > Math.abs(dist2)) {
snappedView = child;
int idxSnap = -1;
for (int i = firstChild; i <= lastChild; i++) {
View view = ((LinearLayoutManager) layoutManager).findViewByPosition(i);
if (view == snappedView) {
idxSnap = i;
break;
}
}
int snapPositionFirst = mOrientationHelper.getDecoratedMeasurement(((LinearLayoutManager) layoutManager).findViewByPosition(firstChild)) / 2;
int snapPositionLast = mOrientationHelper.getTotalSpace() - mOrientationHelper.getDecoratedMeasurement(((LinearLayoutManager) layoutManager).findViewByPosition(lastChild)) / 2;
int centerSnapPosition = mOrientationHelper.getTotalSpace() / 2;
if (idxSnap != -1) {
int currentSmallestDistance = Integer.MAX_VALUE;
View currentSmallestDistanceView = null;
for (int i = firstChild; i <= lastChild; i++) {
View view = ((LinearLayoutManager) layoutManager).findViewByPosition(i);
if (i < idxSnap && firstChild == 0) {
int snapPosition = snapPositionFirst + (i - firstChild) * (centerSnapPosition - snapPositionFirst) / (idxSnap - firstChild);
int viewPosition = view.getLeft() + view.getWidth() / 2;
int dist = snapPosition - viewPosition;
if (Math.abs(dist) < Math.abs(currentSmallestDistance) || (Math.abs(dist) == Math.abs(currentSmallestDistance) && distSnap > 0)) {
currentSmallestDistance = dist;
currentSmallestDistanceView = view;
}
} else if (i > idxSnap && lastChild == (mLlm.getItemCount() - 1)) {
int snapPosition = snapPositionLast - (lastChild - i) * (snapPositionLast - centerSnapPosition) / (lastChild - idxSnap);
int viewPosition = view.getLeft() + view.getWidth() / 2;
int dist = snapPosition - viewPosition;
if (Math.abs(dist) < Math.abs(currentSmallestDistance) || (Math.abs(dist) == Math.abs(currentSmallestDistance) && distSnap < 0)) {
currentSmallestDistance = dist;
currentSmallestDistanceView = view;
}
}
}
} else if (lastChild == (mLlm.getItemCount() - 1)) {
View child = layoutManager.findViewByPosition(lastChild);
if (mOrientationHelper.getDecoratedStart(child) < mOrientationHelper.getTotalSpace() - mOrientationHelper.getDecoratedMeasurement(child) / 2
&& mOrientationHelper.getDecoratedStart(child) < mOrientationHelper.getTotalSpace()) {
int dist1 = super.calculateDistanceToFinalSnap(layoutManager, snappedView)[0];
int dist2 = mOrientationHelper.getTotalSpace() - mOrientationHelper.getDecoratedEnd(child);
if (Math.abs(dist1) > Math.abs(dist2)) {
snappedView = child;
}
if (Math.abs(distSnap) > Math.abs(currentSmallestDistance)) {
snappedView = currentSmallestDistanceView;
mLastSavedTarget = currentSmallestDistanceView;
mLastSavedDistance = -currentSmallestDistance;
}
}
}
@ -71,4 +102,15 @@ public class LinearLayoutManagerSnapHelper extends LinearSnapHelper {
}
return snappedView;
}
@Override
public int[] calculateDistanceToFinalSnap(@NonNull RecyclerView.LayoutManager layoutManager, @NonNull View targetView) {
if (targetView == mLastSavedTarget) {
int[] out = new int[2];
out[0] = mLastSavedDistance;
out[1] = 0;
return out;
}
return super.calculateDistanceToFinalSnap(layoutManager, targetView);
}
}