检测AppBarLayout/CollapsingToolbarLayout何时完全展开

25

我有一个使用新的CoordinatorLayout/AppBarLayout/CollapsingToolbarLayout范例的片段,我想要能够检测到折叠工具栏完全展开时,以便我可以对它所在的整个片段执行操作,例如弹出片段并转到新片段,或关闭片段。我已经有关闭代码运行了,我只需要知道何时使用和何时不使用。

我已经尝试过一些AppBarLayout.OnOffsetChangedListener的实现方式,但运气不佳。是否有一种方法可以使用它来确定何时完全展开,或者有没有更优选的方法?

感谢您的提前帮助!

编辑: 我还看到有一些AppBarLayout.setExpanded(...)的实现方式,但没有类似于AppBarLayout.getExpanded()或其他方法,因此我被卡住了。


也许使用 appBarLayout.addOnOffsetChangedListener 可以帮助,但我发现它有些错误,可能是我没有正确实现。 - mstrengis
你找到解决方法了吗?我遇到了同样的问题,试图防止ScrollRefreshLayout在工具栏部分折叠时刷新。 - Jimeux
3个回答

49

API中似乎没有任何东西,但以下内容对我来说似乎有效。可能需要测试。

boolean fullyExpanded =
    (appBarLayout.getHeight() - appBarLayout.getBottom()) == 0;

编辑:上述解决方案似乎有效,但由于我想在应用栏滚动时测试此条件,我最终使用了以下带有OnOffsetChangedListener的解决方案。


注:本翻译仅供参考,具体语境需要根据实际情况理解。
class Frag extends Fragment implements AppBarLayout.OnOffsetChangedListener {

    private boolean appBarIsExpanded = true;
    private AppBarLayout appBarLayout;

    @Override 
    public void onActivityCreated(Bundle state) {
        super.onActivityCreated(state);
        appBarLayout = (AppBarLayout) getActivity().findViewById(R.id.app_bar);
    }

    @Override
    public void onResume() {
        super.onResume();
        appBarLayout.addOnOffsetChangedListener(this);
    }

    @Override
    public void onStop() {
        super.onStop();
        appBarLayout.removeOnOffsetChangedListener(this);
    }

    @Override
    public void onOffsetChanged(AppBarLayout appBarLayout, int verticalOffset) {
        appBarIsExpanded = (verticalOffset == 0);
    } 

}

我最终放弃了一开始想要做这件事的原因,但既然你说它对你有效,我会接受你的答案。谢谢! - James Pizzurro
这对我也不起作用。已经添加了接口的实现,但似乎没有被调用。 - filthy_wizard
1
@user1232726 你需要将监听器附加到AppBarLayout上。我更新了代码,提供了一种方法来实现这个。如果你不关心潜在的泄漏问题,只需使用appBarLayout.setOnScrollChangeListener(this)即可完成工作。 - Jimeux
2
你刚刚拯救了我的一天。谢谢你。 - v4_adi

10

我的解决方案基于创建一个自定义视图。首先创建一个类,继承本地的AppBarLayout:

public class CustomAppBar extends AppBarLayout { ....

然后在类内设置addOnOffsetChangedListener,像这样:

this.addOnOffsetChangedListener...

您可以通过在构造函数中设置,或者在构造函数内调用方法来完成上述操作。因此,您需要使用带有2个参数的构造函数,请记得使用具有 2 个参数的构造函数以能够被添加到 XML 中:

public CustomAppBar(Context context, AttributeSet attrs) {
        super(context, attrs);
//You can set the listener here or maybe call the method that set the listener
}

接下来我们需要访问视图的状态,因此在自定义视图类中创建一个私有布尔值,并根据需要将其设置为true或false,以指示视图是否默认展开或收起,在这种情况下,我的视图默认展开:

private boolean isExpanded = true;

现在您需要更新该布尔值的状态:

this.addOnOffsetChangedListener(new AppBarLayout.OnOffsetChangedListener() {
            @Override
            public void onOffsetChanged(AppBarLayout appBarLayout, int verticalOffset) {
                if (verticalOffset == 0) {
                    isExpanded = true;
                } else {
                    isExpanded = false;
                }
            }
        });

下一步是在CustomAppBar类中使用getter获取布尔值的状态。

public boolean isExpanded() {
        return isExpanded;
    }

下一步是去你的 xml 文件中,使用你自定义的视图,然后在 Activity 或 Fragment 中获取该视图并使用方法来知道 AppBar 的状态。


当您可以直接将 OnOffsetChangedListener 添加到 AppBarLayout 实例时,似乎这是一种过度设计。 - Aspiring Dev
如果您只打算使用该AppBarLayout一次:是的,它是。但是,如果有多个活动需要了解AppBarLayout状态,则这是DRY解决方案。 - cutiko

8

我知道可能有点晚,但探究了 AppBarLayout 的源代码后,我发现 AppBarLayout.OnOffsetChangedListener 实际上只是将 AppBar 行为的 int getTopAndBottomOffset() 值进行转换。

因此,你可以随时使用以下代码来确定是否展开了 AppBarLayout:

public boolean isAppBArExpanded(AppBarLayout abl) {
    final CoordinatorLayout.Behavior behavior = ((CoordinatorLayout.LayoutParams) abl.getLayoutParams()).getBehavior();
    return (behavior instanceof AppBarLayout.Behavior) ? (((AppBarLayout.Behavior) behavior).getTopAndBottomOffset() == 0) : false;
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接