RecyclerView滚动到指定位置及高度计算

RecyclerView滚动到指定位置及高度计算

滚动到指定位置

由于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版权协议,转载请附上原文出处链接和本声明。