解决RecycleView滑动到指定位置的问题:
相信好多人都用过自定义LinearLayoutManager,如下:
import android.content.Context;
import android.graphics.PointF;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.LinearSmoothScroller;
import android.support.v7.widget.RecyclerView;
import android.util.DisplayMetrics;
/**
* Created by gjl on 2018/3/2.
*/
public class ScrollSpeedLinearLayoutManger extends LinearLayoutManager {
private float MILLISECONDS_PER_INCH = 0.3f;
public ScrollSpeedLinearLayoutManger(Context context) {
super(context);
//根据不同的屏幕分辨率设置速度
MILLISECONDS_PER_INCH = context.getResources().getDisplayMetrics().density * 0.1f;
}
@Override
public void smoothScrollToPosition(RecyclerView recyclerView, RecyclerView.State state, int position) {
LinearSmoothScroller linearSmoothScroller =
new LinearSmoothScroller(recyclerView.getContext()) {
@Override
public PointF computeScrollVectorForPosition(int targetPosition) {
return ScrollSpeedLinearLayoutManger.this
.computeScrollVectorForPosition(targetPosition);
}
//This returns the milliseconds it takes to
//scroll one pixel.
@Override
protected float calculateSpeedPerPixel
(DisplayMetrics displayMetrics) {
//返回滑动一个pixel需要多少毫秒
return MILLISECONDS_PER_INCH / displayMetrics.density;
}
};
linearSmoothScroller.setTargetPosition(position);
startSmoothScroll(linearSmoothScroller);
}
}
使用时:
ScrollSpeedLinearLayoutManger linearLayoutManger = new ScrollSpeedLinearLayoutManger(MainActivity.this);
recycleView.setLayoutManager(linearLayoutManger);
//滑动方法
linearLayoutManger.smoothScrollToPosition(recycleView,null,position);
结果发现滑动方法不好用了,使用smoothScrollToPosition时,移动到前面的项时,它默认会将要显示的项底部,但是移动到后面的项时,它默认会将要显示的项顶部,当前移动项在屏幕上显示时,不会移动,用过的应该都有所了解。
解决问题
从上面的代码看到,我们只是设置了LinearSmoothScroller,那么查看一下LinearSmoothScroller的源码发现:
/**
* Align child view's left or top with parent view's left or top
*
* @see #calculateDtToFit(int, int, int, int, int)
* @see #calculateDxToMakeVisible(android.view.View, int)
* @see #calculateDyToMakeVisible(android.view.View, int)
*/
public static final int SNAP_TO_START = -1;
/**
* Align child view's right or bottom with parent view's right or bottom
*
* @see #calculateDtToFit(int, int, int, int, int)
* @see #calculateDxToMakeVisible(android.view.View, int)
* @see #calculateDyToMakeVisible(android.view.View, int)
*/
public static final int SNAP_TO_END = 1;
/**
* <p>Decides if the child should be snapped from start or end, depending on where it
* currently is in relation to its parent.</p>
* <p>For instance, if the view is virtually on the left of RecyclerView, using
* {@code SNAP_TO_ANY} is the same as using {@code SNAP_TO_START}</p>
*
* @see #calculateDtToFit(int, int, int, int, int)
* @see #calculateDxToMakeVisible(android.view.View, int)
* @see #calculateDyToMakeVisible(android.view.View, int)
*/
public static final int SNAP_TO_ANY = 0;
/**
* When scrolling towards a child view, this method defines whether we should align the top
* or the bottom edge of the child with the parent RecyclerView.
*
* @return SNAP_TO_START, SNAP_TO_END or SNAP_TO_ANY; depending on the current target vector
* @see #SNAP_TO_START
* @see #SNAP_TO_END
* @see #SNAP_TO_ANY
*/
protected int getVerticalSnapPreference() {
return mTargetVector == null || mTargetVector.y == 0 ? SNAP_TO_ANY :
mTargetVector.y > 0 ? SNAP_TO_END : SNAP_TO_START;
}
LinearSmoothScroller里面3个状态,这里我们只需要在设置LinearSmoothScroller的时候重写 getVerticalSnapPreference()方法,让滑动位置始终滑动到条目开始位置就好了.
/**
* Created by gjl on 2018/3/2.
*/
public class ScrollSpeedLinearLayoutManger extends LinearLayoutManager {
private float MILLISECONDS_PER_INCH = 0.3f;
public ScrollSpeedLinearLayoutManger(Context context) {
super(context);
MILLISECONDS_PER_INCH = context.getResources().getDisplayMetrics().density * 0.1f;
}
@Override
public void smoothScrollToPosition(RecyclerView recyclerView, RecyclerView.State state, int position) {
LinearSmoothScroller linearSmoothScroller =
new LinearSmoothScroller(recyclerView.getContext()) {
@Override
public PointF computeScrollVectorForPosition(int targetPosition) {
return ScrollSpeedLinearLayoutManger.this
.computeScrollVectorForPosition(targetPosition);
}
//This returns the milliseconds it takes to
//scroll one pixel.
@Override
protected float calculateSpeedPerPixel
(DisplayMetrics displayMetrics) {
return MILLISECONDS_PER_INCH / displayMetrics.density;
//返回滑动一个pixel需要多少毫秒
}
//重写这个方法,保证滑动到指定条目的顶部
@Override
protected int getVerticalSnapPreference() {
return SNAP_TO_START;
}
};
linearSmoothScroller.setTargetPosition(position);
startSmoothScroll(linearSmoothScroller);
}
}