2 votes

Présentation d'un fragment sur un fragment à fond transparent

J'utilise la navigation par jetpack pour passer d'un fragment à un fragment de détail.

J'ai besoin d'aide pour présenter le fragment de détail sur le fragment qui l'affiche.

Voir la photo ci-dessous pour voir ce que j'essaie d'obtenir :

Eiffel Tower

J'utilise également un fade_in / fade_out de base pour l'entrée et la sortie dans les animations du graphique de navigation.

Voici le résultat que j'obtiens :

result of presenting view not showing up in the detail view

Comment puis-je configurer la transition pour que le fragment de détail s'affiche au-dessus de la vue de présentation ?

Voici tous mes progrès :

menu_nav_bas

<menu xmlns:android="http://schemas.android.com/apk/res/android">

    <item
            android:id="@+id/fragment_tab1"
            android:title="Tab 1"/>

    <item
            android:id="@+id/fragment_tab2"
            android:title="Tab 2"/>

    <item
            android:id="@+id/fragment_tab3"
            android:title="Tab 3"/>

</menu>

nav_graph

<navigation 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:id="@+id/nav_graph"
            app:startDestination="@id/fragment_tab1">
    <fragment android:id="@+id/fragment_tab1" android:name="com.example.navgraphfragmentmodal.Tab1" android:label="fragment_tab1"
              tools:layout="@layout/fragment_tab1">
        <action android:id="@+id/toModal" app:destination="@id/modalFragment"/>
    </fragment>
    <fragment android:id="@+id/fragment_tab2" android:name="com.example.navgraphfragmentmodal.Tab2" android:label="fragment_tab2"
              tools:layout="@layout/fragment_tab2"/>
    <fragment android:id="@+id/fragment_tab3" android:name="com.example.navgraphfragmentmodal.Tab3"
              android:label="fragment_tab3" tools:layout="@layout/fragment_tab3"/>
    <fragment android:id="@+id/modalFragment" android:name="com.example.navgraphfragmentmodal.ModalFragment"
              android:label="fragment_modal" tools:layout="@layout/fragment_modal"/>
</navigation>

MainActivity.kt

class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        val navHostFragment = supportFragmentManager.findFragmentById(R.id.navigation_host_fragment) as NavHostFragment?
        NavigationUI.setupWithNavController(bottom_navigation_view, navHostFragment!!.navController)

        supportActionBar?.setDisplayShowHomeEnabled(true)
    }

    override fun onOptionsItemSelected(item: MenuItem): Boolean {
        supportActionBar?.setDisplayShowHomeEnabled(false)
        if (item.itemId === android.R.id.home) {
            //Title bar back press triggers onBackPressed()
            onBackPressed()
            return true
        }
        return super.onOptionsItemSelected(item)
    }

    //Both navigation bar back press and title bar back press will trigger this method
    override fun onBackPressed() {
        supportActionBar?.setDisplayShowHomeEnabled(false)
        if (supportFragmentManager.backStackEntryCount > 0) {
            supportFragmentManager.popBackStack()
        } else {
            super.onBackPressed()
        }
    }
}

Fragment Tab1 (C'est le fragment avec l'image de la Tour Eiffel et le bouton)

class Tab1 : Fragment() {

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        // Inflate the layout for this fragment
        return inflater.inflate(R.layout.fragment_tab1, container, false)
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        learnMoreButton.setOnClickListener {
            NavHostFragment.findNavController(this).navigate(R.id.modalFragment)
        }
    }

}

Modification de la prime :

Je cherche à afficher un fragment sur un fragment dans un graphe de navigation, comme on le voit dans l'image de la Tour Eiffel. Dans iOS, cela serait similaire à la présentation : Sur le plein écran. Je le fais. no Je souhaite utiliser un DialogFragment, car j'ai beaucoup plus de contrôle sur l'animation des vues dans un Fragment normal.

9voto

crysxd Points 802

Vous essayez d'ajouter une boîte de dialogue modale à un graphique de navigation en tant que destination normale. NavController n'affiche toujours qu'une seule destination à la fois et elles ne sont pas empilées. Un fragment est supprimé de la vue lorsqu'un autre est affiché par NavController. Il n'est pas prévu qu'il fonctionne de la manière dont vous le souhaitez.

Vous devez créer un AlertDialog ou un DialogFragment avec votre interface utilisateur. Dans le cas présenté ci-dessus, un AlertDialog sera déjà suffisante. Vous pouvez ajouter une vue personnalisée à une AlertDialog comme ça :

val dialog = AlertDialog.Builder(context)
    .setView(R.layout.your_layout)
    .show()

dialog.findViewById<View>(R.id.button).setOnClickListener {
   // Do somehting
   dialog.dismiss()
}

Cela vous permet de créer un dialogue avec votre vue personnalisée. Elle fonctionnera comme on le souhaiterait : Cliquer sur le bouton ferme la boîte de dialogue, tout comme appuyer sur le bouton retour. L'arrière-plan sera automatiquement atténué.

La boîte de dialogue aura la forme par défaut, mais vous pouvez suivre les instructions suivantes ce pour créer les coins arrondis de la boîte de dialogue présentée dans votre question.

Vous pouvez ajouter des animations à l AlertDialog avec des animations de fenêtre et un style personnalisé, consultez la rubrique cette réponse .

Pour les vues plus complexes nécessitant un cycle de vie DialogFragment doit être utilisé (par exemple, lors de l'affichage d'une carte dans le dialogue). À partir de la navigation 2.1.0-alpha03 <dialog> sont prises en charge. Cette fonctionnalité est encore en phase alpha/bêta.

Edit :

Si vous souhaitez un contrôle extrêmement fin des animations, vous pouvez ajouter une vue à votre mise en page comme ceci :

<FrameLayout>

   <!-- Remove the defaultNavHost from this! -->
   <fragment android:id="@+id/navHost" android:name="...NavHost" />

   <FrameLayout android:id="@+id/dialog" android:background="#44000000" android:layout_width="match_parent" android:layout_height="match_parent">

       <FrameLayout android:id="@+id/dialogContent" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center">

           <!-- Dialog contents -->

       </FramyLayout>

   </FrameLayout>

</FrameLayout>

Comme l'élément se trouve après l'hôte de navigation dans la mise en page, il sera rendu au-dessus de celui-ci. Sachez que les boutons ou autres éléments ayant l'attribut elevation peut apparaître par-dessus.

Enfin, écrasez votre onBackPressed() dans votre activité pour rétablir le comportement de navigation :

override fun onBackPressed() {
    val dialog = findViewById<View>(R.id.dialog)
    val navController = (supportFragmentManager.findFragmentById(R.id.navHost) as NavHostFragment).navController
    if (dialog.visibility == View.VISIBLE) {
        hideDialog()
    } else if(navController.popBackStack()) {
        Log.i("MainActivity", "NavController handled back press")
    } else {
        super.onBackPressed()
    }
}

private fun showDialog() {
    findViewById<View>(R.id.dialog).visibility = View.VISIBLE
    // Intro animation
}

private fun hideDialog() {
    // Outro animation. Call the next line after the animation is done.
    findViewById<View>(R.id.dialog).visibility = View.GONE
}

C'est peut-être ce que vous cherchez, mais je ne le recommande pas et je travaille avec AlertDialog o DialogFragment à la place.

Vous pouvez également utiliser une nouvelle activité avec un arrière-plan transparent pour le dialogue et désactiver les animations de cette activité afin d'animer manuellement les vues dans l'activité. Les activités peuvent être 100% transparentes.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X