滚动到指定位置
由于RecyclerView的布局复用,看不到的item是暂时没有添加到RecyclerView中的,所以要滚动到看不到的item所在位置时,调用smoothScrollToPosition(int position)并不能滚动到目标位置。
实现思路,每次滚动到最后一个可见item之前,循环滚动,直到滚动到目标位置为止。
/**
* 优化了 smoothScrollToPosition()
* Created by zhangjianliang on 2017/11/20
*/
public class MyLinearLayoutManager extends LinearLayoutManager {
/** 目标项是否在最后一个可见项之后 */
private boolean mShouldScroll;
/** 记录目标项位置 */
private int mToPosition;
private Context mContext;
private SmoothScrollListener mSmoothScrollListener = new SmoothScrollListener();
/**
* 滑动到指定位置
*/
public void smoothToPosition(RecyclerView recyclerView, final int position) {
if (recyclerView == null || recyclerView.getChildCount() <= 0) {
return;
}
recyclerView.removeOnScrollListener(mSmoothScrollListener);
recyclerView.addOnScrollListener(mSmoothScrollListener);
smoothMoveToPosition(recyclerView, position);
}
private void smoothMoveToPosition(RecyclerView recyclerView, final int position) {
// 第一个可见位置
int firstItem = recyclerView.getChildLayoutPosition(recyclerView.getChildAt(0));
// 最后一个可见位置
int lastItem = recyclerView.getChildLayoutPosition(recyclerView.getChildAt(recyclerView.getChildCount() - 1));
if (position < firstItem) {// 如果跳转位置在第一个可见位置之前,就smoothScrollToPosition可以直接跳转
recyclerView.smoothScrollToPosition(position);
} else if (position <= lastItem) {// 跳转位置在第一个可见项之后,最后一个可见项之前
// smoothScrollToPosition根本不会动,此时调用smoothScrollBy来滑动到指定位置
int movePosition = position - firstItem;
if (movePosition >= 0 && movePosition < recyclerView.getChildCount()) {
View targetView = recyclerView.getChildAt(movePosition);
if (targetView == null) {
return;
}
recyclerView.smoothScrollBy(0, targetView.getTop());
}
} else {// 如果要跳转的位置在最后可见项之后,则先调用smoothScrollToPosition将要跳转的位置滚动到可见位置
// 再通过onScrollStateChanged控制再次调用smoothMoveToPosition,执行上一个判断中的方法
recyclerView.smoothScrollToPosition(position);
mToPosition = position;
mShouldScroll = true;
}
}
private class SmoothScrollListener extends RecyclerView.OnScrollListener {
@Override
public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
super.onScrollStateChanged(recyclerView, newState);
if (mShouldScroll) {
mShouldScroll = false;
smoothMoveToPosition(recyclerView, mToPosition);
}
}
}
}
高度计算
public class MyLinearLayoutManager extends LinearLayoutManager {
private ILayoutCompleteListener mListener;
@Override
public void onLayoutCompleted(RecyclerView.State state) {
super.onLayoutCompleted(state);
int count = getChildCount();
int itemsHeight = 0;
for (int i = 0; i < count; i++) {
View item = getChildAt(i);
if (item == null) {
continue;
}
itemsHeight += item.getMeasuredHeight();
}
if (mListener != null) {
mListener.onLayoutCompleted(itemsHeight);
}
}
public void setLayoutCompleteListener(ILayoutCompleteListener listener) {
mListener = listener;
}
public interface ILayoutCompleteListener {
void onLayoutCompleted(int itemsHeight);
}
}
/**
* 用于计算recyclerview高度
* Created by zhangjianliang on 2019/8/6
*/
public class MyGridLayoutManager extends GridLayoutManager {
private ILayoutCompleteListener mListener;
public MyGridLayoutManager(Context context, int spanCount, ILayoutCompleteListener listener) {
super(context, spanCount);
mListener = listener;
}
@Override
public void onLayoutCompleted(RecyclerView.State state) {
super.onLayoutCompleted(state);
int spanCount = getSpanCount();
int count = getChildCount();
int lines = count / spanCount;
if (count % spanCount > 0) {
lines += 1;
}
int itemsHeight = 0;
View item = getChildAt(0);
if (item != null) {
itemsHeight += item.getMeasuredHeight();
}
if (mListener != null) {
mListener.onLayoutCompleted(itemsHeight * lines);
}
}
public void setLayoutCompleteListener(ILayoutCompleteListener listener) {
mListener = listener;
}
public interface ILayoutCompleteListener {
void onLayoutCompleted(int itemsHeight);
}
}
版权声明:本文为u010577768原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。