我快速地将一个简单的解决方案放在一起,基于.它并不完美,你可以花一些时间对它进行微调,但它还不错。无论如何,结果应该看起来像这样:CoordinatorLayout.Behavior
在我开始回答之前,作为一个小的旁注:我强烈建议您使用 来自支持库 而不是普通的 .它们在任何方面都是相同的,但实现在较低的 API 级别上正确的嵌套滚动行为。NestedScrollView
ScrollView
NestedScrollView
无论如何,让我们从我的答案开始:我想出的解决方案可以与任何可滚动的容器一起使用,无论是 ,还是您不需要子类化任何容器即可实现它。ScrollView
ListView
RecyclerView
Views
首先,如果您尚未使用Google的设计支持库,则需要将其添加到您的项目中:
compile 'com.android.support:design:25.0.1'
请记住,如果您的目标不是API级别25(顺便说一句,您应该这样做),那么您需要包含API级别的最新版本(例如。 对于 API 级别 24)。compile 'com.android.support:design:24.2.0'
无论您使用什么可滚动容器,都需要包装在布局中。在我的示例中,我使用:CoordinatorLayout
NestedScrollView
<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v4.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="match_parent">
<!-- content -->
</android.support.v4.widget.NestedScrollView>
</android.support.design.widget.CoordinatorLayout>
允许您将 a 分配给其直接子视图。在这种情况下,我们将为将要实现的超滚动反弹效果分配一个。CoordinatorLayout
Behavior
Behavior
NestedScrollView
让我们来看看代码:Behavior
public class OverScrollBounceBehavior extends CoordinatorLayout.Behavior<View> {
private int mOverScrollY;
public OverScrollBounceBehavior() {
}
public OverScrollBounceBehavior(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
public boolean onStartNestedScroll(CoordinatorLayout coordinatorLayout, View child, View directTargetChild, View target, int nestedScrollAxes) {
mOverScrollY = 0;
return true;
}
@Override
public void onNestedScroll(CoordinatorLayout coordinatorLayout, View child, View target, int dxConsumed, int dyConsumed, int dxUnconsumed, int dyUnconsumed) {
if (dyUnconsumed == 0) {
return;
}
mOverScrollY -= dyUnconsumed;
final ViewGroup group = (ViewGroup) target;
final int count = group.getChildCount();
for (int i = 0; i < count; i++) {
final View view = group.getChildAt(i);
view.setTranslationY(mOverScrollY);
}
}
@Override
public void onStopNestedScroll(CoordinatorLayout coordinatorLayout, View child, View target) {
final ViewGroup group = (ViewGroup) target;
final int count = group.getChildCount();
for (int i = 0; i < count; i++) {
final View view = group.getChildAt(i);
ViewCompat.animate(view).translationY(0).start();
}
}
}
解释a是什么以及它们是如何工作的超出了这个答案的范围,所以我只是要快速解释上面的代码的作用。拦截 在 的直接子级中发生的所有滚动事件。在方法中,我们返回,因为我们对任何滚动事件感兴趣。在我们查看参数中,它告诉我们滚动容器没有消耗多少垂直滚动(换句话说,overscroll),然后按该量转换滚动容器的子级。由于我们只是获得增量值,因此我们需要在变量中对所有这些值进行求和。 在滚动事件停止时调用。这是当我们将滚动容器的所有子级动画化回其原始位置时。Behavior
Behavior
CoordinatorLayout
onStartNestedScroll()
true
onNestedScroll()
dyUnconsumed
mOverscrollY
onStopNestedScroll()
要将 分配给 ,我们需要使用 xml 属性并传入要使用的 的完整类名。在我的示例中,上面的类在包中,因此我必须设置为值。 是 的自定义属性,因此我们需要在它前面加上正确的命名空间:Behavior
NestedScrollView
layout_behavior
Behavior
com.github.wrdlbrnft.testapp
com.github.wrdlbrnft.testapp.OverScrollBounceBehavior
layout_behavior
CoordinatorLayout
<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v4.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="com.github.wrdlbrnft.testapp.OverScrollBounceBehavior">
<!-- content -->
</android.support.v4.widget.NestedScrollView>
</android.support.design.widget.CoordinatorLayout>
请注意我在 上添加的命名空间和在 上添加的属性。CoordinatorLayout
app:layout_behavior
NestedScrollView
这就是你所要做的!虽然这个答案比我预期的要长,但我跳过了一些基础知识,包括和。因此,如果您不熟悉这些或有任何其他进一步的问题,请随时提问。CoordinatorLayout
Behaviors