我有一个CoordinatorLayout
有两个孩子,一个View
充当标题和一个RecyclerView
:
<android.support.design.widget.CoordinatorLayout
android:id="@+id/coordinator"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:id="@+id/view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:gravity="center_horizontal"
app:layout_behavior="some.package.AlphaBehavior">
<ImageView
android:id="@+id/header_iv"
style="@style/some_style"/>
<TextView
android:id="@+id/header_retails_tv"
style="@style/some_style_tv"
android:text="@string/some_text"/>
</LinearLayout>
<android.support.v7.widget.RecyclerView
android:id="@+id/recyclerview"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clipToPadding="false" />
</android.support.design.widget.CoordinatorLayout>
我将填充动态设置RecyclerView
为标题的大小并将其设置clipToPadding
为false
,因此RecyclerView
显示在标题下方,当用户向上滚动时,RecyclerView
显示在标题视图上方。
我做了一个自定义CoordinatorLayout.Behavior
,以便在用户向上滚动时实现淡出视图,list
并在标题必须再次可见时淡入AlphaBehavior
:
public class AlphaBehavior extends CoordinatorLayout.Behavior {
private float alpha = 1.0f;
private float scrolly = 0.f;
private int headerSize = 0;
private Animation defaultFadeInAnimation;
public AlphaBehavior(Context context, AttributeSet attrs) {
super(context, attrs);
defaultFadeInAnimation = AnimationUtils.loadAnimation(context, android.R.anim.fade_in);
}
public void setHeaderSize(int headerSize) {
this.headerSize = headerSize;
}
@Override
public boolean layoutDependsOn(CoordinatorLayout parent, View child, View dependency) {
return dependency instanceof RecyclerView;
}
@Override
public void onNestedScroll(CoordinatorLayout coordinatorLayout, View child, View target, int dxConsumed, int dyConsumed, int dxUnconsumed, int dyUnconsumed) {
scrolly += dyConsumed;
Log.d(Constants.TAG, dyConsumed + "/" + dyUnconsumed + "/" + scrolly);
float totalScrollY = ((RecyclerView)target).computeVerticalScrollOffset();
Log.d(Constants.TAG, "totalScrollY:" + totalScrollY);
alpha = (headerSize - totalScrollY) / headerSize;
if (alpha < 0.f) alpha = 0.f;
if (alpha > 1.0f) alpha = 1.f;
if (dyConsumed < 0 && totalScrollY > headerSize) {
alpha = 0.f;
}
Log.d(Constants.TAG, "alpha:" + alpha);
child.setAlpha(alpha);
}
@Override
public void onStopNestedScroll(CoordinatorLayout coordinatorLayout, View child, View target) {
int pos = ((LinearLayoutManager)((RecyclerView)target).getLayoutManager()).findFirstCompletelyVisibleItemPosition();
Log.d(Constants.TAG, "pos:" + pos);
if (pos == 0 && child.getAlpha() == 0.f) {
child.startAnimation(defaultFadeInAnimation);
}
}
// overriding this in case we don't the other events are not called
@Override
public boolean onStartNestedScroll(CoordinatorLayout coordinatorLayout, View child, View directTargetChild, View target, int nestedScrollAxes) {
return nestedScrollAxes == ViewCompat.SCROLL_AXIS_VERTICAL;
}
}
但我面临一个问题:如果用户滚动速度非常快,则行为事件无法正确调用。该scrollY
成员与总滚动关系不佳,并且该totalScrollY
成员(通过计算来自 的滚动获得RecyclerView
)不正确。即使我试图firstCompletelyVisibleItem
在事件中找到 ,但是当达到列表的开头onStopNestedScroll
时它会返回位置 2 或 3 。recyclerView