(二)一个很尿性问题:重新刷新后 recyclerView.smoothScrollBy(-100, 0); 不起作用

上一篇提到:一个很尿性问题:重新刷新后 recyclerView.smoothScrollBy(-100, 0); 不起作用

再次细心查发现上一篇处理虽然解决问题但没有找到根源,再次细研究调试分析发现

smoothScrollBy 为什么x方向为负数不是向左滑动呢

smoothScrollBy(int dx, int dy) 方法中,X方向的滑动距离确实应该是负数表示向左滑动。

如果 smoothScrollBy(int dx, int dy) 方法中 dx 参数为负数,而不是向左滑动,可能有以下几个原因:

  1. 滚动容器的布局方向可能是从右往左的,或者是水平反向布局。这种情况下,滑动操作会按照布局方向进行相反的移动。这样,dx 参数为正数就表示向左滑动,而负数表示向右滑动。

  2. 滚动容器的滚动方向可能是垂直方向的,而不是水平方向。这种情况下,dx 参数是用来控制水平滑动的,负数表示向左滑动,但可能因为滚动容器的滚动方向不对,导致滑动方向不符合预期。

  3. 其他代码逻辑或方法调用有问题,导致滑动效果不正确。你可以检查一下这个方法的调用位置,确保传入正确的参数值。

最后进一步测试,发现我的滚动容器的布局方向可能是从右往左的,所以一直没有反应,待改变dx值大于0 时居然往左了

怎么知道滚动容器的布局方向是从右往左的,或者是水平反向布局 ?

要确定滚动容器的布局方向是从右往左的,或者是水平反向布局,可以查看容器的布局属性(LayoutParams)或者样式(Style)。

方法一:查看布局属性(LayoutParams)
如果你有访问滚动容器的布局属性的权限,可以尝试检查以下属性:

1. 如果滚动容器是一个 `ViewGroup` 的子类(如 `LinearLayout`、`RelativeLayout`、`FrameLayout`等),你可以通过获取其布局参数来查看布局方向是否被设置为从右往左。例如,对于 `LinearLayout`,可以通过以下方式检查:

LinearLayout.LayoutParams params = (LinearLayout.LayoutParams) scrollView.getLayoutParams();
if (params.getLayoutDirection() == View.LAYOUT_DIRECTION_RTL) {
    // 布局方向是从右往左
} else {
    // 默认布局方向
}

2. 如果滚动容器是一个 `RecyclerView`,你可以尝试检查其 `LayoutManager` 的布局方向是否被设置为从右往左。例如,对于 `LinearLayoutManager`,可以通过以下方式检查:

LinearLayoutManager layoutManager = (LinearLayoutManager) recyclerView.getLayoutManager();
if (layoutManager.getReverseLayout()) {
    // 布局方向是从右往左
} else {
    // 默认布局方向
}


方法二:查看样式(Style)
如果你可以访问滚动容器的样式文件(XML文件),可以尝试查看样式中的相关属性。

1. 在滚动容器的样式中,查找是否有 `android:layoutDirection` 属性。如果该属性的值是 `rtl`,则布局方向是从右往左。

2. 同样,在滚动容器的样式中,你也可以查找是否有像 `android:orientation` 这样的属性。如果该属性的值是 `horizontal_reverse`,则布局方向是水平反向布局。

通过查看布局属性或样式,你应该能够确定滚动容器的布局方向,从而正确理解滑动方向。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
抱歉,我的回答还是有误。这是因为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等功能。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值