2
votes

Comment masquer la barre d'application inférieure lors du défilement dans Android

Je suis en train de créer une application Android qui a une activité et une autre activité implémente l'activité principale.Maintenant, je mets également en œuvre une activité avec plusieurs modèles de fragments. Voici la mise en page de mon activité principale.

<?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>

Vous pouvez voir que mon activité principale contient une mise en page dans laquelle je traite tous les fragments.J'ai utilisé le bouton d'image à la place du bouton d'action flottant car je veux un bouton d'action flottant de forme ovale.Maintenant, qu'est-ce que je veux ce fragment intérieur lorsque l'utilisateur fait défiler puis le bouton d'image, la barre d'application inférieure et la vue qui est la ligne horizontale se cache? La barre d'application inférieure est utilisée dans de nombreux fragments, j'ai donc besoin d'un code que je peux écrire dans une activité qui masque la barre d'application inférieure et le bouton d'image pendant que les utilisateurs font défiler le fragment. Comment puis-je y parvenir? Je suis désolé pour ma question idiote car je suis nouveau dans le développement Android. Merci d'avance.


0 commentaires

4 Réponses :


2
votes

Vous pouvez y parvenir en mettant les deux lignes ci-dessous en 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"/>

Ainsi, la balise xml complète sera

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


7 commentaires

et qu'en est-il du bouton d'image et de la vue qui est une ligne horizontale juste au-dessus de la barre d'application inférieure


Gardez à l'esprit que si un FAB est présent, il se détache de la barre et reste à l'écran. Le défilement vers le haut affiche la barre d'application inférieure et se rattache à un FAB.


Ouais je sais que frère je te demande comment je cache aussi le bouton d'image et la vue


Et utilisez FloatingActionButton au lieu de votre propre bouton d'image.


Si vous utilisez scrollView ou RecyclerView, vous pouvez également masquer le FAB en implémentant l'écouteur onScoll.


puis-je rendre le bouton d'action flottant de forme ovale?


continuons cette discussion dans le chat .



0
votes

Vous pouvez y parvenir en ajoutant l'attribut suivant à votre BottomAppBar:

app:layout_behavior="@string/hide_bottom_view_on_scroll_behavior"


2 commentaires

et qu'en est-il du bouton d'image et de la vue qui est une ligne horizontale juste au-dessus de la barre d'application inférieure


Pour la réinitialisation des éléments, je suggérerais d'écouter le changement de défilement de la vue du recycleur et de les masquer / afficher en fonction de la valeur de dy .



1
votes

Étant donné que vous faites défiler à l'intérieur d'un fragment, vous devez transmettre les valeurs de défilement à votre activité.

Je vous suggère d'utiliser InteractionInterface par défaut qu'Android Studio a généré dans le modèle de Fragment: p >

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
}

Et puis, dans YourActivity , implémentez YourFragment.OnFragmentInteractionListener

Remplacez la fonction

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
}

le résultat ressemblera à ce lien mp4

Le point principal est: Passez votre action de défilement de Fragment à Activité, Vous pouvez y parvenir de plusieurs manières, ce n'est que la base;


0 commentaires

1
votes

Une approche similaire à celle de Wesely est la suivante.

Supposons que nous ayons quelque chose comme ceci:
image
Une barre d'applications inférieure personnalisée et nous avons au moins un fragment par action. Ce que je veux dire, c'est que l'activité main est le parent où tous les fragments vont être placés.

Vous pouvez déclarer une interface dans l'activité principale ( dans cet exemple, je veux masquer / afficher une barre d'applications inférieure personnalisée et FAB) pour afficher / masquer la barre d'applications inférieure et fab (les deux dans activity_main.xml), donc l ' interface ressemblerait à quelque chose comme ceci:

<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>

Une fois que l'interface est définie dans l'activité principale, chaque fragment avec une vue de défilement imbriquée peut l'implémenter.

XXX

Créer une référence à NestedScrollView et attacher le onScrollChangeListener nous aidera à vérifier quand il y a un changement dans le défilement sur le y axis

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
    }
}

Rappelez-vous que dans Kotlin, nous pouvons utiliser _ lorsque le paramètre dans le lambda n'est jamais utilisé. Donc, fondamentalement, le changement dans y est val dy = oldScrollY - scrollY et dy est négatif lorsque le le défilement est de bas en haut et cette condition dy est vraie, nous utilisons donc le contexte de la vue pour appeler OnScrollListenerMain.fabAndBottomAppBarHide ()
et encore dy est positif lorsque le défilement est de haut en bas et que cette condition dy> 0 est vraie, nous utilisons donc le contexte du view pour invoquer OnScrollListenerMain.fabAndBottomAppBarShow()

Mais, que se passe-t-il si nous voulons simplement cacher une BottomAppbar (sans masquer FAB)?

La BottomAppbar pourrait être l'enfant de la mise en page Coordinator et les fragments doivent avoir un NestedScrollView, RecyclerView ou ScrollView comme parent dans leur XML, de sorte que l'activité principale XML devrait ressembler à quelque chose comme:

<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>

Les fragments devraient être placé dans lly_main et cette ligne fait l'affaire: app:hideOnScroll="true"


0 commentaires