NestedScrollView 在 Nougat 上抛出停止错误(API 25)
NestedScrollView fling stopping bug on Nougat (API 25)
Nexus 5x (7.1.2) 和 Google Pixel (7.1.1) 上的 NestedScrollView fling 有一个奇怪的问题。在其他 OS 版本上它工作正常。
滑动动画有时会在抬起手指后立即停止。它卡住了,接下来的几次尝试也可能会停止。
为了重现它,你需要上下投掷几次。
在日志中,这些投掷在速度、方向等方面看起来几乎相同,所以我找不到这个错误的真正原因。
另外,NestedScrollView
不一定要在CoordinatorLayout
里面,也可以根本没有NestedScrollingChild
。
例如,此错误可通过以下 NestedScrollView
children 之一重现:
1) LinearLayout
填充 TextViews
2) WebView
3) LinearLayout
填充了 RecyclerViews
.
我知道 RecyclerView
和 CoordinatorLayout
内的行为可能存在的问题,但这不相关。
所以请不要提及任何
recyclerView.getLayoutManager().setAutoMeasureEnabled(true);
recyclerView.setNestedScrollingEnabled(false);
或类似的东西。
代码示例:
<android.support.v4.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fillViewport="true">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="16dp"
android:text="Put a super long text here"/>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="16dp"
android:text="Put a super long text here"/>
</LinearLayout>
</android.support.v4.widget.NestedScrollView>
所以这显然是 NestedScrollView 中的一个错误。
我已经为此做了一个解决方法,但仍在等待 Google 方面的正确修复。
https://github.com/Dimezis/FlingableNestedScrollView/
编辑:
看起来问题已在支持库 26.0.0-beta2 中修复
https://chris.banes.me/2017/06/09/carry-on-scrolling/
编辑 2:
虽然滚动现在工作正常,但在我的应用程序中我可以不断重现此错误:
https://issuetracker.google.com/issues/37051723
如果有人也遇到它,您可以在提到的线程中找到解决方法。
根据Animating a Scroll Gesture training guide,在覆盖 computeScroll() 时,在使用 mScroller.computeScrollOffset() 计算滚动视图的适当偏移量后,我们需要使用:
ViewCompat.postInvalidateOnAnimation(this);
为下一个滚动设置动画。
但是,在 NestedScrollView 中,computeScroll() 看起来像这样:
public void computeScroll() {
if (mScroller.computeScrollOffset()) {
...
}
}
不请求下一个滚动动画!这意味着在使用mScroller.fling(...)之后,computeScroll()方法有时只会被调用一次,并且视图不会一直闪烁。
为了解决这个问题,我尝试用这种方式替换 computeScroll:
public void computeScroll(){
if(mScroller.computeScrollOffset()){
...
ViewCompat.postInvalidateOnAnimation(this);
}
}
这听起来可能不是一个好的解决方案,但目前它工作得很好。
最新版本的 NestedScrollView 添加了 ViewCompat.postInvalidateOnAnimation(this)。
Nexus 5x (7.1.2) 和 Google Pixel (7.1.1) 上的 NestedScrollView fling 有一个奇怪的问题。在其他 OS 版本上它工作正常。
滑动动画有时会在抬起手指后立即停止。它卡住了,接下来的几次尝试也可能会停止。 为了重现它,你需要上下投掷几次。
在日志中,这些投掷在速度、方向等方面看起来几乎相同,所以我找不到这个错误的真正原因。
另外,NestedScrollView
不一定要在CoordinatorLayout
里面,也可以根本没有NestedScrollingChild
。
例如,此错误可通过以下 NestedScrollView
children 之一重现:
1) LinearLayout
填充 TextViews
2) WebView
3) LinearLayout
填充了 RecyclerViews
.
我知道 RecyclerView
和 CoordinatorLayout
内的行为可能存在的问题,但这不相关。
所以请不要提及任何
recyclerView.getLayoutManager().setAutoMeasureEnabled(true);
recyclerView.setNestedScrollingEnabled(false);
或类似的东西。
代码示例:
<android.support.v4.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fillViewport="true">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="16dp"
android:text="Put a super long text here"/>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="16dp"
android:text="Put a super long text here"/>
</LinearLayout>
</android.support.v4.widget.NestedScrollView>
所以这显然是 NestedScrollView 中的一个错误。 我已经为此做了一个解决方法,但仍在等待 Google 方面的正确修复。
https://github.com/Dimezis/FlingableNestedScrollView/
编辑:
看起来问题已在支持库 26.0.0-beta2 中修复
https://chris.banes.me/2017/06/09/carry-on-scrolling/
编辑 2: 虽然滚动现在工作正常,但在我的应用程序中我可以不断重现此错误:
https://issuetracker.google.com/issues/37051723
如果有人也遇到它,您可以在提到的线程中找到解决方法。
根据Animating a Scroll Gesture training guide,在覆盖 computeScroll() 时,在使用 mScroller.computeScrollOffset() 计算滚动视图的适当偏移量后,我们需要使用:
ViewCompat.postInvalidateOnAnimation(this);
为下一个滚动设置动画。 但是,在 NestedScrollView 中,computeScroll() 看起来像这样:
public void computeScroll() {
if (mScroller.computeScrollOffset()) {
...
}
}
不请求下一个滚动动画!这意味着在使用mScroller.fling(...)之后,computeScroll()方法有时只会被调用一次,并且视图不会一直闪烁。
为了解决这个问题,我尝试用这种方式替换 computeScroll:
public void computeScroll(){
if(mScroller.computeScrollOffset()){
...
ViewCompat.postInvalidateOnAnimation(this);
}
}
这听起来可能不是一个好的解决方案,但目前它工作得很好。
最新版本的 NestedScrollView 添加了 ViewCompat.postInvalidateOnAnimation(this)。