我制作了一个包含recyclerview
和floating 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>
答案 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();
}
}
});