'scrollBy(int, androidx.recyclerview.widget.RecyclerView.Recycler, androidx.recyclerview.widget.RecyclerView.State)' is not public in 'androidx.recyclerview.widget.LinearLayoutManager'. Cannot be accessed from outside package
时间: 2023-10-30 14:30:51 浏览: 166
抱歉,我的回答还是有误。这是因为scrollBy是LinearLayoutManager的一个非公开的方法,只能在LinearLayoutManager内部使用,不能从外部访问。因此,我们需要通过其他方式来实现RecyclerView的平滑滚动。以下是一个基于Scroller类的实现方法:
```
public void smoothScrollBy(int dx, int dy) {
RecyclerView.SmoothScroller smoothScroller = new LinearSmoothScroller(getContext()) {
@Override
public PointF computeScrollVectorForPosition(int targetPosition) {
return LinearLayoutManager.this.computeScrollVectorForPosition(targetPosition);
}
};
smoothScroller.setTargetPosition(getPositionForVelocity(dx, dy));
startSmoothScroll(smoothScroller);
}
protected int getPositionForVelocity(int dx, int dy) {
if (getChildCount() == 0) {
return 0;
}
final View nearestChild = findNearestChild();
if (nearestChild == null) {
return 0;
}
final int currentPosition = getPosition(nearestChild);
if (currentPosition == RecyclerView.NO_POSITION) {
return 0;
}
final int direction = computeScrollDirectionForPosition(currentPosition, dx, dy);
if (direction == RecyclerView.NO_POSITION) {
return 0;
}
final int targetPosition = currentPosition + direction;
if (targetPosition < 0 || targetPosition >= getItemCount()) {
return 0;
}
return targetPosition;
}
protected int computeScrollDirectionForPosition(int targetPosition, int dx, int dy) {
if (getChildCount() == 0) {
return RecyclerView.NO_POSITION;
}
final View firstChild = getChildAt(0);
if (firstChild == null) {
return RecyclerView.NO_POSITION;
}
final int currentPosition = getPosition(firstChild);
if (currentPosition == RecyclerView.NO_POSITION) {
return RecyclerView.NO_POSITION;
}
final int direction = getScrollDirectionForPosition(currentPosition, targetPosition);
if (direction == RecyclerView.NO_POSITION) {
return RecyclerView.NO_POSITION;
}
final int distance = computeDistanceToPosition(targetPosition);
if (distance == 0) {
return RecyclerView.NO_POSITION;
}
return (int) Math.ceil((double) distance / (double) getDistancePerChild());
}
protected int getDistancePerChild() {
return Math.round(getChildAt(0).getHeight() * 1.0f);
}
protected int computeDistanceToPosition(int targetPosition) {
final int targetChildIndex = targetPosition - getPosition(getChildAt(0));
return targetChildIndex * getDistancePerChild();
}
protected int getScrollDirectionForPosition(int currentPosition, int targetPosition) {
return targetPosition < currentPosition ? -1 : 1;
}
protected View findNearestChild() {
final int childCount = getChildCount();
if (childCount == 0) {
return null;
}
View nearestChild = null;
int nearestDistance = Integer.MAX_VALUE;
final int centerX = getWidth() / 2;
final int centerY = getHeight() / 2;
for (int i = 0; i < childCount; i++) {
final View child = getChildAt(i);
final int distanceX = Math.abs(getLeftDecorationWidth(child) + getRightDecorationWidth(child) + child.getMeasuredWidth() / 2 - centerX);
final int distanceY = Math.abs(getTopDecorationHeight(child) + getBottomDecorationHeight(child) + child.getMeasuredHeight() / 2 - centerY);
final int distance = distanceX * distanceX + distanceY * distanceY;
if (distance < nearestDistance) {
nearestChild = child;
nearestDistance = distance;
}
}
return nearestChild;
}
```
这个实现方法是通过LinearSmoothScroller来实现的,首先创建一个LinearSmoothScroller对象,然后设置目标位置,最后启动平滑滚动。在getPositionForVelocity、computeScrollDirectionForPosition、computeDistanceToPosition和findNearestChild等函数中,实现了计算滚动距离、滚动方向、目标位置和最近的子View等功能。
阅读全文