【问题标题】:F.A.B Hides but Doesn't ShowF.A.B 隐藏但不显示
【发布时间】:2017-07-13 20:41:56
【问题描述】:

试图实现一个Floating Action Button (F.A.B),它在向下滚动时隐藏,在向上滚动时显示。

我有 ScrollAwareFABBehavior.java 来管理它,它在 XML activity_main 中连接到 F.A.B。 问题: F.A.B 在向下滚动时隐藏,但在我向上滚动时不再显示。我记录了onNestedScroll 方法,它在向下滚动时调用“调用滚动”和“调用隐藏”;但是在隐藏 F.A.B 之后,没有 3x Log's

问题:为什么我在隐藏 F.A.B 后向上滚动时不显示 F.A.B。

ScrollAwareFABBehavior.java:

import android.content.Context;
import android.support.design.widget.CoordinatorLayout;
import android.support.design.widget.FloatingActionButton;
import android.support.v4.view.ViewCompat;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;

public class ScrollAwareFABBehavior extends FloatingActionButton.Behavior {
    public ScrollAwareFABBehavior(Context context, AttributeSet attrs) {
        super();
    }

    @Override
    public boolean onStartNestedScroll(final CoordinatorLayout coordinatorLayout, final FloatingActionButton child,
                                       final View directTargetChild, final View target, final int nestedScrollAxes) {
        // Ensure we react to vertical scrolling
        return nestedScrollAxes == ViewCompat.SCROLL_AXIS_VERTICAL
                || super.onStartNestedScroll(coordinatorLayout, child, directTargetChild, target, nestedScrollAxes);
    }

    @Override
    public void onNestedScroll(final CoordinatorLayout coordinatorLayout, final FloatingActionButton child,
                               final View target, final int dxConsumed, final int dyConsumed,
                               final int dxUnconsumed, final int dyUnconsumed) {
        super.onNestedScroll(coordinatorLayout, child, target, dxConsumed, dyConsumed, dxUnconsumed, dyUnconsumed);
        Log.d("test", "calling scroll");
        if (dyConsumed > 0 && child.getVisibility() == View.VISIBLE) {
            // User scrolled down and the FAB is currently visible -> hide the FAB
            Log.d("test", "calling to hide");
            child.hide();
        } else if (dyConsumed < 0 && child.getVisibility() != View.VISIBLE) {
            // User scrolled up and the FAB is currently not visible -> show the FAB
            Log.d("test", "calling to show");
            child.show();
        }
    }
}

activity_main.xml:

<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:id="@+id/main_content"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="companyname.appname.MainActivity">


        <android.support.v7.widget.RecyclerView xmlns:android="http://schemas.android.com/apk/res/android"
            android:id="@+id/rv_contactlist"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:clipToPadding="false"
            android:paddingBottom="16dp"
            android:paddingTop="16dp"
            android:scrollbars="vertical" />

        <android.support.design.widget.FloatingActionButton

            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="bottom|end"
            android:layout_margin="16dp"
            android:src="@drawable/ic_add_circle_outline_black_24dp"
            app:layout_anchor="@id/rv_contactlist"
            app:layout_anchorGravity="bottom|right|end"
            android:layout_alignParentEnd="true"
            app:fabSize="normal"
            android:layout_alignParentBottom="true"
            android:onClick="addItem"
            app:layout_behavior="companyname.appname.ScrollAwareFABBehavior"/>

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

【问题讨论】:

  • 你有没有试过这个stackoverflow.com/questions/32038332/…
  • 我认为child.hide(); 现在将视图设置为GONE 而不是INVISIBLE,因此此代码将不起作用。检查.hide() 所做的确认...
  • @MarkKeen 我可以用什么代替?
  • 您需要检查.hide() 的作用以确认我所说的。如果是这种情况,只需调整代码来处理这种情况。或者(不推荐,但如果您不想努力重构代码)回滚到 FloatingActionButton 的早期库版本 - 我相信它是设计支持库的一部分

标签: java android android-coordinatorlayout floating-action-button


【解决方案1】:

您在项目中使用的是哪个支持库版本?

如果您使用的是最新版本(我的意思是 25.0.x),这是因为 fab.hide() 方法将可见性设置为 View.GONE。这使得嵌套滚动侦听器停止检查 fab,这是您第二次尝试滚动列表时。

更多细节可以在这里找到:https://code.google.com/p/android/issues/detail?id=230298

我搜索了一下发现这个类似的问题已经有一个很好的答案: Floating action button not visible on scrolling after updating Google Support & Design Library

因此,一种可能的解决方法是覆盖 fab.hide 方法,而不是将可见性设置为 GONE 而是 INVISIBLE。

而且我认为这可能会在稍后从上游修复,所以请密切关注它。

【讨论】:

  • 非常感谢!你让我很开心:)
  • 只需要在 hide child.hide(new FloatingActionButton.OnVisibilityChangedListener() { @Override public void onHidden(FloatingActionButton fab) { super.onShown(fab); fab.setVisibility(View.不可见); } });
【解决方案2】:

由于Android更新到25.0.x+,您应该将带有监听器的fab按钮设置为INVISBLE以再次显示fab按钮,我的解决方案是下一个:

public class ScrollAwareFABBehavior extends FloatingActionButton.Behavior {
private static final String TAG = "ScrollAwareFABBehavior";

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


@Override
public boolean onStartNestedScroll(@NonNull CoordinatorLayout coordinatorLayout, @NonNull FloatingActionButton child, @NonNull View directTargetChild, @NonNull View target, int axes, int type) {
    return true;
}

@Override
public boolean layoutDependsOn(CoordinatorLayout parent, FloatingActionButton child, View dependency) {
    if(dependency instanceof RecyclerView)
        return true;

    return false;
}

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

    if (dyConsumed > 0 && child.getVisibility() == View.VISIBLE) {
        child.hide(new FloatingActionButton.OnVisibilityChangedListener() {
                       @Override
                       public void onHidden(FloatingActionButton fab) {
                           super.onHidden(fab);
                           fab.setVisibility(View.INVISIBLE);
                       }
                   }
        );
    } else if (dyConsumed < 0 && child.getVisibility() != View.VISIBLE) {
        child.show();
    }
}
}

** 在装有 Android Oreo 的 Nexus 6P 中测试。

【讨论】:

  • 这是针对 Android Oreo 而非 Android Pie 版本的解决方案
【解决方案3】:

使用之前建议的双重检查方法。一个工厂可以同时显示和不可见,所以对于完美的显示工厂:

fab.show(); fab.setVisibility(View.VISIBLE);

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多