如何在android中滚动时隐藏底部的应用栏

时间:2019-03-18 06:43:17

标签: android android-fragments

我正在制作一个具有活动的android应用程序,其他活动实现了主要活动。现在我还实现了一个活动的多个片段模式,因此每个活动中至少包含7-8个片段。 这是我主要活动的布局。

<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.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"
    tools:context=".MainActivity">

<FrameLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="60dp"
    android:id="@+id/frame_lay">

</FrameLayout>



<View
    android:layout_width="match_parent"
    android:layout_height="4dp"
    android:layout_above="@id/bottom_appbar"
    app:layout_anchor="@+id/bottom_appbar"

    android:background="@android:color/darker_gray"/>

<com.google.android.material.bottomappbar.BottomAppBar
    android:id="@+id/bottom_appbar"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_gravity="bottom"
    app:backgroundTint="@color/colorbottomappbar"
    app:fabAlignmentMode="center"
    app:navigationIcon="@drawable/ic_menu_green_24dp">

</com.google.android.material.bottomappbar.BottomAppBar>



<ImageButton
    android:id="@+id/fab"
    android:layout_width="190dp"
    android:layout_height="80dp"
    android:visibility="visible"
    app:layout_anchorGravity="center_horizontal|bottom"
    android:background="@drawable/logo"
    app:layout_anchor="@+id/bottom_appbar"
    android:layout_marginBottom="17dp"/>

<ImageButton
    android:id="@+id/fab_two"
    android:layout_width="190dp"
    android:layout_height="80dp"
    android:visibility="gone"
    app:layout_anchorGravity="center_horizontal|bottom"
    android:background="@drawable/logotwo"
    android:elevation="5dp"
    app:layout_anchor="@+id/bottom_appbar"
    android:layout_marginBottom="13dp">


</ImageButton>

您可以看到我的主要活动具有框架布局,可以在其中处理所有片段。我使用图像按钮代替浮动动作按钮,因为我想要椭圆形的浮动动作按钮。现在我想要片段内的内容当用户滚动时,图像按钮,bottomappbar和水平线的视图是否隐藏?底部的应用栏在许多片段中都被使用,因此我需要可以在活动中编写的代码,该代码在用户滚动片段时会隐藏底部的应用栏和图像按钮。我如何实现此目的?对于我的愚蠢问题,我感到抱歉,因为我是android开发的新手。谢谢。

4 个答案:

答案 0 :(得分:0)

您可以通过将以下两行放在xml中来实现

app:hideOnScroll="true"
app:layout_scrollFlags="scroll|enterAlways"

因此完整的xml标签将是

<com.google.android.material.bottomappbar.BottomAppBar
    android:id="@+id/bottom_app_bar"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_gravity="bottom"
    app:fabAlignmentMode="center"
    app:hideOnScroll="true"
    app:layout_scrollFlags="scroll|enterAlways"/>

答案 1 :(得分:0)

您可以通过在BottomAppBar中添加以下属性来实现此目的:

app:layout_behavior="@string/hide_bottom_view_on_scroll_behavior"

答案 2 :(得分:0)

因为要在“片段”中滚动,所以需要将滚动值传递给活动。

我建议您使用Fragment模板中Android Studio生成的默认InteractionInterface

override fun onCreateView(
    inflater: LayoutInflater, container: ViewGroup?,
    savedInstanceState: Bundle?
): View? {
    val root = inflater.inflate(R.layout.fragment_blank, container, false)
    root.scrollView2.setOnScrollChangeListener { v, scrollX, scrollY, oldScrollX, oldScrollY ->
        // the key is here.
        var delta = scrollY - oldScrollY
        listener?.onFragmentScrolled(delta)
    }
    return inflater.inflate(R.layout.fragment_blank, container, false)
}


interface OnFragmentInteractionListener {
    // Name your function here
    fun onFragmentScrolled(delta: Float)
}

// the lines below are generated,
// not the key point here but important to binding listener
override fun onAttach(context: Context) {
    super.onAttach(context)
    if (context is OnFragmentInteractionListener) {
        listener = context
    } else {
        throw RuntimeException(context.toString() + " must implement OnFragmentInteractionListener")
    }
}

override fun onDetach() {
    super.onDetach()
    listener = null
}

然后在YourActivity中实现YourFragment.OnFragmentInteractionListener

覆盖功能

override fun onFragmentScrolled(delta: Float) {
    anotherView.translationY = anotherView.translationY + delta
    if (anotherView.translationY > anotherView.height)
        anotherView.translationY = anotherView.height.toFloat()
    if (anotherView.translationY < 0)
        anotherView.translationY = 0f
}

结果将像这样mp4 link

要点是:将滚动动作从“片段”传递到“活动”, 您可以通过多种方式实现这一目标,这只是基本目标;

答案 3 :(得分:0)

以下是与Wesely相似的方法。

假设我们有这样的东西:
 picture
自定义底部应用栏,每个动作至少有一个片段。 我的意思是,活动主体是所有片段都将放置在其中的父对象。

您可以在主要活动中声明一个 界面 (在此示例中,我要隐藏/显示自定义底部应用栏和FAB)以执行底部的显示/隐藏appbar和fab(它们都在activity_main.xml中),因此 界面 看起来像这样:

class MainActivity : AppCompatActivity(), OnScrollListenerMain {
...

    override fun fabAndBottomAppBarHide() {
        if (fab_main.isVisible) {
            fab_main.hide()
            bottom_app_bar.performHide()
        }
    }

    override fun fabAndBottomAppBarShow() {
        if (!fab_main.isVisible) {
            fab_main.show()
            bottom_app_bar.performShow()
        }
    }
...
} // end Main 

interface OnScrollListenerMain {
    fun fabAndBottomAppBarHide()
    fun fabAndBottomAppBarShow()
}

一旦在主要活动中定义了接口,具有嵌套滚动视图的每个片段都可以实现该接口。

<androidx.core.widget.NestedScrollView xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/nsv_fragment_with_scroll"
    ... >

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">
        ...
    </LinearLayout>

</androidx.core.widget.NestedScrollView>

创建对NestedScrollView的引用并附加onScrollChangeListener将有助于我们检查 y 轴上滚动的时间是否发生变化

class FragmentWithScroll : Fragment() {
lateinit var mScroll:NestedScrollView
...
override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?,savedInstanceState: Bundle?): View? {
        // Inflate the layout for this fragment
        val view = inflater.inflate(R.layout.fragment_with_scroll,container,false)
        mScroll = view.findViewById(R.id.nsv_fragment_with_scroll)

        mScroll.setOnScrollChangeListener { v: NestedScrollView?, _: Int, scrollY: Int, _: Int, oldScrollY: Int ->
            val dy = oldScrollY - scrollY
            if (dy < 0) {
                (v!!.context as OnScrollListenerMain).fabAndBottomAppBarHide()
            } else if (dy > 0) {
                (v!!.context as OnScrollListenerMain).fabAndBottomAppBarShow()
            }
        }
        ...
        return view
    }
}

请记住,当从未使用过lambda中的参数时,我们可以使用 _ 。 因此, y 的变化基本上是val dy = oldScrollY - scrollY,而 dy 在滚动是从底部到顶部时是负的。 strong>并且此条件dy < 0为真,因此我们使用视图的上下文来调用OnScrollListenerMain.fabAndBottomAppBarHide()
再次 dy 为正(当滚动是从上到下时)并且此条件dy > 0为true,因此我们使用视图的上下文来调用{{ 1}}

但是,如果我们只想隐藏BottomAppbar(不隐藏FAB)怎么办?

BottomAppbar可能是Coordinator布局的子级,并且片段需要在其XML中具有NestedScrollView,RecyclerView或ScrollView作为父级,因此主要活动XML的外观应类似于:

OnScrollListenerMain.fabAndBottomAppBarShow()

应将片段放入 lly_main 中,这一行可以解决问题:<androidx.coordinatorlayout.widget.CoordinatorLayout android:id="@+id/coordinator_main" android:layout_width="match_parent" android:layout_height="match_parent"> <LinearLayout android:id="@+id/lly_main" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" /> <com.google.android.material.floatingactionbutton.FloatingActionButton android:id="@+id/fab_main" android:layout_width="wrap_content" android:layout_height="wrap_content" android:adjustViewBounds="true" android:src="@drawable/ic_add" app:borderWidth="0dp" app:layout_anchor="@+id/bottom_app_bar" /> <com.google.android.material.bottomappbar.BottomAppBar android:id="@+id/bottom_app_bar" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_gravity="bottom" app:fabAlignmentMode="center" app:hideOnScroll="true"> </com.google.android.material.bottomappbar.BottomAppBar> </androidx.coordinatorlayout.widget.CoordinatorLayout>