Files
EhViewer/app/src/main/java/com/hippo/easyrecyclerview/LayoutManagerUtils.java
T
2021-01-24 17:28:16 +08:00

154 lines
6.6 KiB
Java

/*
* Copyright 2015 Hippo Seven
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.hippo.easyrecyclerview;
import android.content.Context;
import android.graphics.PointF;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import androidx.recyclerview.widget.StaggeredGridLayoutManager;
import com.hippo.yorozuya.MathUtils;
import com.hippo.yorozuya.SimpleHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public final class LayoutManagerUtils {
private static Method sCsdfp = null;
static {
try {
sCsdfp = StaggeredGridLayoutManager.class.getDeclaredMethod("calculateScrollDirectionForPosition", int.class);
sCsdfp.setAccessible(true);
} catch (NoSuchMethodException e) {
// Ignore
e.printStackTrace();
}
}
public static void scrollToPositionWithOffset(
RecyclerView.LayoutManager layoutManager, int position, int offset) {
if (layoutManager instanceof LinearLayoutManager) {
((LinearLayoutManager) layoutManager).scrollToPositionWithOffset(position, offset);
} else if (layoutManager instanceof StaggeredGridLayoutManager) {
((StaggeredGridLayoutManager) layoutManager).scrollToPositionWithOffset(position, offset);
} else {
throw new IllegalStateException("Can't do scrollToPositionWithOffset for " +
layoutManager.getClass().getName());
}
}
public static void smoothScrollToPosition(
RecyclerView.LayoutManager layoutManager, Context context, int position) {
smoothScrollToPosition(layoutManager, context, position, -1);
}
public static void smoothScrollToPosition(
RecyclerView.LayoutManager layoutManager, Context context, int position,
int millisecondsPerInch) {
SimpleSmoothScroller smoothScroller;
if (layoutManager instanceof LinearLayoutManager) {
final LinearLayoutManager linearLayoutManager = (LinearLayoutManager) layoutManager;
smoothScroller = new SimpleSmoothScroller(context, millisecondsPerInch) {
@Override
public PointF computeScrollVectorForPosition(int targetPosition) {
return linearLayoutManager.computeScrollVectorForPosition(targetPosition);
}
};
} else if (layoutManager instanceof StaggeredGridLayoutManager) {
final StaggeredGridLayoutManager staggeredGridLayoutManager = (StaggeredGridLayoutManager) layoutManager;
smoothScroller = new SimpleSmoothScroller(context, millisecondsPerInch) {
@Override
public PointF computeScrollVectorForPosition(int targetPosition) {
int direction = 0;
try {
direction = (Integer) sCsdfp.invoke(staggeredGridLayoutManager, targetPosition);
} catch (IllegalAccessException | InvocationTargetException e) {
e.printStackTrace();
}
if (direction == 0) {
return null;
}
if (staggeredGridLayoutManager.getOrientation() == StaggeredGridLayoutManager.HORIZONTAL) {
return new PointF(direction, 0);
} else {
return new PointF(0, direction);
}
}
};
} else {
throw new IllegalStateException("Can't do smoothScrollToPosition for " +
layoutManager.getClass().getName());
}
smoothScroller.setTargetPosition(position);
layoutManager.startSmoothScroll(smoothScroller);
}
public static void scrollToPositionProperly(final RecyclerView.LayoutManager layoutManager,
final Context context, final int position, final OnScrollToPositionListener listener) {
SimpleHandler.getInstance().postDelayed(() -> {
int first = getFirstVisibleItemPosition(layoutManager);
int last = getLastVisibleItemPosition(layoutManager);
int offset = Math.abs(position - first);
int max = last - first;
if (offset < max && max > 0) {
smoothScrollToPosition(layoutManager, context, position,
MathUtils.lerp(100, 25, (offset / max)));
} else {
scrollToPositionWithOffset(layoutManager, position, 0);
if (listener != null) {
listener.onScrollToPosition(position);
}
}
}, 200);
}
public static int getFirstVisibleItemPosition(RecyclerView.LayoutManager layoutManager) {
if (layoutManager instanceof LinearLayoutManager) {
return ((LinearLayoutManager) layoutManager).findFirstVisibleItemPosition();
} else if (layoutManager instanceof StaggeredGridLayoutManager) {
int[] positions = ((StaggeredGridLayoutManager) layoutManager).findFirstVisibleItemPositions(null);
return MathUtils.min(positions);
} else {
throw new IllegalStateException("Can't do getFirstVisibleItemPosition for " +
layoutManager.getClass().getName());
}
}
public static int getLastVisibleItemPosition(RecyclerView.LayoutManager layoutManager) {
if (layoutManager instanceof LinearLayoutManager) {
return ((LinearLayoutManager) layoutManager).findLastVisibleItemPosition();
} else if (layoutManager instanceof StaggeredGridLayoutManager) {
int[] positions = ((StaggeredGridLayoutManager) layoutManager).findLastVisibleItemPositions(null);
return MathUtils.max(positions);
} else {
throw new IllegalStateException("Can't do getLastVisibleItemPosition for " +
layoutManager.getClass().getName());
}
}
public interface OnScrollToPositionListener {
void onScrollToPosition(int position);
}
}