【问题标题】:BottomNavigationView does not hide on scrolling inside fragment, if fragment contains AppBarLayout如果片段包含 AppBarLayout,BottomNavigationView 不会在片段内部滚动时隐藏
【发布时间】:2019-02-24 07:57:08
【问题描述】:

我在使用 Android 中的 coordinatorLayout 在片段中滚动和检测它时遇到了很多问题。我有一个包含 3 个片段的“MainActivity”。在其中一个片段中,我有一个 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。

任何形式的帮助都将不胜感激。

【问题讨论】:

  • 在没有应用栏布局的情况下,事情是否按预期工作?
  • 是的,它完全可以在没有应用栏布局的情况下工作。基本问题是应用栏布局中使用了滚动标志。它正在消耗底部导航行为所需的滚动事件。
  • 提供的答案是否适合您,如果不是,是什么问题?

标签: android scroll bottomnavigationview android-appbarlayout


【解决方案1】:

为了隐藏底部导航以响应片段内部的滚动 修改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 个片段的所有回收器视图。如果有一些标志或其他任何东西使得bottomnavigation能够获取滚动事件(即使片段使用带有滚动标志的应用栏布局),因为已经定义了隐藏/显示bottomNav的行为(只需要获取滚动事件),那就太好了直接地)。此功能存在于 Cricbuzz 应用程序中,我想知道他们是如何做到的
  • 我认为您可以将代码提取到单独的函数中。
  • 您是否尝试过将侦听器代码移动到分离 fn?
【解决方案2】:

将您的库更新为28.0.0 or aboveandroidx / material-1.0.0 并更改您的BottomNavigationView,如下所示-

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

希望对您有所帮助。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-11-16
    • 1970-01-01
    • 1970-01-01
    • 2021-06-02
    • 1970-01-01
    • 2017-11-20
    相关资源
    最近更新 更多