【发布时间】:2017-02-05 01:19:38
【问题描述】:
我有一个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 显示在标题下方,当用户向上滚动时,@987654330 @ 显示在标题视图上方。
我制作了一个自定义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 的滚动获得)不正确。即使我试图在onStopNestedScroll 事件中找到firstCompletelyVisibleItem,但是当recyclerView 到达列表的开头时,它会返回位置2 或3。
【问题讨论】:
-
请查看 Ian Lake 的answer。
标签: android android-recyclerview coordinator-layout