当一个Fragment包含AppBarLayout时,BottomNavigationView在滚动时不会隐藏。

5
我在使用Android中的CoordinatorLayout时,在Fragment中滚动和检测有很多问题。我有一个名为“MainActivity”的主要活动,其中包含3个片段。其中一个片段中有一个Appbar,当片段滚动时会折叠。我已经成功做到了这一点,但如果我设置滚动行为以允许它,我的bottomNavigationView(在mainactivity.xml中找到)将不会对滚动作出反应。代码大致如下: Fragment1.xml
<android.support.design.widget.CoordinatorLayout
...
...>
    <android.support.design.widget.AppBarLayout
 ...
 ...>
        <android.support.design.widget.CollapsingToolbarLayout
                 app:layout_scrollFlags="scroll|exitUntilCollapsed"
   ...>
            <android.support.v7.widget.Toolbar
     .../>
        </android.support.design.widget.CollapsingToolbarLayout>
    </android.support.design.widget.AppBarLayout>

   <android.support.v4.widget.NestedScrollView
        app:layout_behavior="@string/appbar_scrolling_view_behavior">
   </android.support.v4.widget.NestedScrollView>

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

MainActivity.xml

<android.support.design.widget.CoordinatorLayout
.../>
    <FrameLayout
        app:layout_behavior="@string/appbar_scrolling_view_behavior"
 .../>
    <android.support.design.widget.BottomNavigationView
      app:layout_behavior="@string/hide_bottom_view_on_scroll_behavior"
.../>
</android.support.design.widget.CoordinatorLayout>

现在,这种方式已经运行得足够好了,当我在片段内滚动时,我的AppBar会折叠成标题(这正是我想要的),但是我的bottomNavigationView并没有对滚动做出反应。
我发现如果加入以下代码:
app:layout_behavior="@string/appbar_scrolling_view_behavior"

通过对AppBarLayout的xml声明,我可以在滚动事件中使bottomView折叠(向上滚动时再次显示)。因此基本上要么我可以在片段内折叠appbar,要么就是当我在片段内检测到滚动事件时我具有隐藏BottomNavigationView的能力。
任何形式的帮助都将不胜感激。

当没有应用栏布局时,事情是否按预期工作? - user158
是的,没有应用程序栏布局它可以完全正常工作。基本问题在于滚动标志被用于应用程序栏布局中。这会消耗底部导航行为所需的滚动事件。 - Robin Sharma
1
提供的答案对您有用吗?如果不行,问题出在哪里? - user158
2个回答

3
为了在滚动 fragment 内容时隐藏底部导航栏,需要修改 fragment1.kt 中的 onCreateView 方法如下。
override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {

        ...

        // access the bottom nav which is on the main activity
        val bottomNav: BottomNavigationView = activity!!.findViewById(R.id.bottom_nav)

        // hide bottom nav when scrolling
        rvList.addOnScrollListener(object : RecyclerView.OnScrollListener() {

            override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
                if (dy > 0 || dy < 0) {
                    bottomNav.visibility = View.GONE
                }
            }

            override fun onScrollStateChanged(recyclerView: RecyclerView, newState: Int) {
                if (newState == RecyclerView.SCROLL_STATE_IDLE) {
                    bottomNav.visibility = View.VISIBLE
                }

                super.onScrollStateChanged(recyclerView, newState)
            }
        })

        return view
}

在Java中

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
        Bundle savedInstanceState) {
        ...

    // access the bottom nav which is on the main activity
    BottomNavigationView bottomNav = getActivity.findViewById(R.id.bottom_nav);

    // hide bottom nav when scrolling
    recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener()
    {
        @Override
        public void onScrolled(RecyclerView recyclerView, int dx, int dy)
        {
             if (dy > 0 ||dy<0)
             {
                 bottomNav.setVisibility(View.GONE);
             }
        }

        @Override
        public void onScrollStateChanged(RecyclerView recyclerView, int newState)
        {
             if (newState == RecyclerView.SCROLL_STATE_IDLE)
             {
                  bottomNav.setVisibility(View.VISIBLE);
             }

             super.onScrollStateChanged(recyclerView, newState);
        }
    });

        return view;
 }

更新:

将监听器代码提取到单独的函数中,如下所示(使用Kotlin)

   public fun hideBottomNav(
        rvList: RecyclerView,
        bottomNav: BottomNavigationView
    ) {
        rvList.addOnScrollListener(object : RecyclerView.OnScrollListener() {

            override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
                if (dy > 0 || dy < 0) {
                    bottomNav.visibility = View.GONE
                }
            }

            override fun onScrollStateChanged(recyclerView: RecyclerView, newState: Int) {
                if (newState == RecyclerView.SCROLL_STATE_IDLE) {
                    bottomNav.visibility = View.VISIBLE
                }

                super.onScrollStateChanged(recyclerView, newState)
            }
        })
    }

谢谢解决方案。它有效,但我认为这个问题一定有更好的解决方案。我需要在我的5个片段活动中都有这种行为,然后我必须将此侦听器应用于所有5个片段的回收站视图。如果有某些标志或其他任何东西,那么底部导航栏就能够获取滚动事件(即使片段使用具有滚动标志的应用程序栏布局),因为隐藏/显示bottomNav的行为已经定义好了(只需要直接获取滚动事件)。这个功能在Cricbuzz应用程序中存在,我想知道他们是如何做到的。 - Robin Sharma
我认为您可以将代码提取到一个单独的函数中。 - user158
你尝试过将监听器代码移到单独的函数中吗? - user158

0

将您的库更新到28.0.0或更高版本或者androidx/material-1.0.0,并像下面这样更改您的BottomNavigationView-

<BottomNavigationView
        android:id="@+id/navigation"
        .
        .
        .
        .
        app:layout_behavior="@string/hide_bottom_view_on_scroll_behavior" />

希望这对你有所帮助。


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