滚动感知FAB隐藏,但随后不再出现

时间:2017-01-13 18:54:46

标签: android android-layout

我制作了一个包含recyclerviewfloating action button的Android应用。向下滚动时,按钮应隐藏,向上滚动时应再次显示。我使用this tutorial来实现行为。

结果是,当我向下滚动时FAB会隐藏,但是当向上滚动时它不会再次出现:(类ScrollAwareFABBehavior与教程相同。但我使用的是嵌套布局。

以下是我的布局(recyclerview位于LinearLayout中的content_main):

<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:fitsSystemWindows="true"
    tools:context="org.myorganisation.mypackage.someActivity">

    <include layout="@layout/toolbar" />

    <include layout="@layout/content_main" />

    <android.support.design.widget.FloatingActionButton
        android:id="@+id/add_fab"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="bottom|end"
        android:layout_margin="@dimen/fab_margin"
        android:src="@drawable/plus"
        app:layout_behavior="org.myorganisation.mypackage.someActivity.helpers.ScrollAwareFABBehavior" />

    <LinearLayout
        android:id="@+id/insert_alert"
        android:layout_width="wrap_content"
        android:layout_height="50sp"
        android:layout_margin="@dimen/fab_margin"
        android:gravity="center_vertical"
        android:orientation="horizontal"
        android:paddingEnd="70sp"
        android:visibility="gone"
        app:layout_anchor="@id/add_fab"
        app:layout_anchorGravity="bottom|left">

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:gravity="center_vertical"
            android:text="@string/initial_alert"
            android:textColor="@color/colorPrimaryDark"
            android:textStyle="bold|italic" />

        <ImageView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:src="@drawable/ic_keyboard_arrow_right_black_24sp"
            android:tint="@color/colorPrimary" />
    </LinearLayout>

</android.support.design.widget.CoordinatorLayout>

4 个答案:

答案 0 :(得分:3)

自支持库版本25.1.0起,隐藏视图不再按this bug滚动事件。

comment #5中所述:

  

这是按预期工作的,您的依赖链是错误的方式。您的RecyclerView(行为)应该触发FAB可见性更改。

答案 1 :(得分:2)

对于支持库版本25.1.0解决方案here

答案 2 :(得分:1)

我通过替换解决了这个问题 .setVisibility(View.VISIBLE)with .show(true)and .setVisibility(View.GONE)与.hide(true):

这是我的行为类,适用于25.1.0:和Clans FloatingActionButton

public class ScrollAwareFABBehavior extends CoordinatorLayout.Behavior<FloatingActionButton> {
private static boolean mIsAnimatingOut = false;
private static final Interpolator INTERPOLATOR = new FastOutSlowInInterpolator();

public ScrollAwareFABBehavior(Context context, AttributeSet attrs) {
    super();
}

@Override
public boolean layoutDependsOn(CoordinatorLayout parent, FloatingActionButton fabButton, View dependency) {
    return dependency instanceof Snackbar.SnackbarLayout;
}

@Override
public boolean onDependentViewChanged(CoordinatorLayout parent, FloatingActionButton fabButton, View dependency) {
    float translationY = Math.min(0, dependency.getTranslationY() - dependency.getHeight());
    fabButton.setTranslationY(translationY);
    return true;
}

@Override
public boolean onStartNestedScroll(CoordinatorLayout coordinatorLayout,
                                   FloatingActionButton fabButton, View directTargetChild, View target, int nestedScrollAxes) {
    return nestedScrollAxes == ViewCompat.SCROLL_AXIS_VERTICAL ||
            super.onStartNestedScroll(coordinatorLayout, fabButton, directTargetChild, target,
                    nestedScrollAxes);

}

@Override
public void onNestedScroll(CoordinatorLayout coordinatorLayout, FloatingActionButton fabButton,
                           View target, int dxConsumed, int dyConsumed, int dxUnconsumed, int dyUnconsumed) {
    super.onNestedScroll(coordinatorLayout, fabButton, target, dxConsumed, dyConsumed, dxUnconsumed,
            dyUnconsumed);

    if (fabButton.isEnabled()) {
        if (dyConsumed > 0 && !mIsAnimatingOut && fabButton.isShown()) {
            animateOut(fabButton);
        } else if ((dyConsumed < 0 || dyUnconsumed < 0) && fabButton.isHidden()) {
            animateIn(fabButton);
        }
    }
}

public static void animateOut(final FloatingActionButton fabButton) {
    if (Build.VERSION.SDK_INT >= 14) {
        ViewCompat.animate(fabButton).translationY(168F).alpha(0.0F).setInterpolator(INTERPOLATOR).withLayer()
                .setListener(new ViewPropertyAnimatorListener() {
                    public void onAnimationStart(View view) {
                        mIsAnimatingOut = true;
                    }

                    public void onAnimationCancel(View view) {
                        mIsAnimatingOut = false;
                    }

                    public void onAnimationEnd(View view) {
                        mIsAnimatingOut = false;
                        fabButton.hide(true);
                    }
                }).start();
    } else {
        Animation anim = AnimationUtils.loadAnimation(fabButton.getContext(), android.R.anim.fade_in);
        anim.setInterpolator(INTERPOLATOR);
        anim.setDuration(200L);
        anim.setAnimationListener(new Animation.AnimationListener() {
            public void onAnimationStart(Animation animation) {
                mIsAnimatingOut = true;
            }

            public void onAnimationEnd(Animation animation) {
                mIsAnimatingOut = false;
                fabButton.hide(true);
            }

            @Override
            public void onAnimationRepeat(final Animation animation) {
            }
        });
        fabButton.startAnimation(anim);
    }
}

public static void animateIn(FloatingActionButton fabButton) {
    fabButton.show(true);
    if (Build.VERSION.SDK_INT >= 14) {
        ViewCompat.animate(fabButton).translationY(0).scaleX(1.0F).scaleY(1.0F).alpha(1.0F)
                .setInterpolator(INTERPOLATOR).withLayer().setListener(null)
                .start();
    } else {
        Animation anim = AnimationUtils.loadAnimation(fabButton.getContext(), android.R.anim.fade_out);
        anim.setDuration(200L);
        anim.setInterpolator(INTERPOLATOR);
        fabButton.startAnimation(anim);
    }
}

}

答案 3 :(得分:0)

这是一个简单的解决方案:

这背后的概念非常简单,您只需要检测用户何时向下滚动RecyclerView。在Android中,有一些内置方法可以帮助我们检测用户何时在Recyclerview中滚动。请参阅下面的代码,因为它将显示完整的概念:

RecyclerView rv = (RecyclerView)findViewById(R.id.rv);
FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);

       rv.addOnScrollListener(new RecyclerView.OnScrollListener() {
          @Override
          public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
                super.onScrollStateChanged(recyclerView, newState);
          }

          @Override
          public void onScrolled(RecyclerView recyclerView, int dx, int dy) {

              if (dy < 0) {
                  fab.show();

               } else if (dy > 0) {
                  fab.hide();
               }
         }
       });