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.
4 Réponses :
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"
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 .
Vous pouvez y parvenir en ajoutant l'attribut suivant à votre BottomAppBar
:
app:layout_behavior="@string/hide_bottom_view_on_scroll_behavior"
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
.
É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;
Une approche similaire à celle de Wesely est la suivante.
Supposons que nous ayons quelque chose comme ceci:
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"