I have a question because there is something I can't do with the fragment display of the android app.

I want to achieve

The app we are currently creating has a navigation at the bottom of the screen and a list view of fragments at the top, and we are creating an app that displays the next fragment by tapping the items in the list. The fragment has up to 3 layers, and the details of the item selected by the user (term explanation, etc.) are displayed in the 3rd layer.
Replace (R.id. ○○, the following fragment) is used to rewrite the fragment.


However, when I tap an item displayed in the list, the next fragment is displayed in an overlapping manner.

Also, when I press the back key of Android, I want to return to the fragment of the previous layer, but it is a situation where I skip everything and return to the first layer.

What I tried

When I looked it up, there was information that "fragments drawn in XML should not be removed or replaced", so I wrote the code as follows based on that. I wrote a temporary FlameLayout in XML and immediately replaced it with the first fragment "homeFragment" with onCreate.

<!-Navigation part at the bottom-><com.google.android.material.bottomnavigation.BottomNavigationView
        android: id = "@ + id/nav_view"
        android: layout_width = "0dp"
        android: layout_height = "wrap_content"
        android: layout_marginStart = "0dp"
        android: layout_marginEnd = "0dp"
        android: background = "? android: attr/windowBackground"
        app: layout_constraintBottom_toBottomOf = "parent"
        app: layout_constraintLeft_toLeftOf = "parent"
        app: layout_constraintRight_toRightOf = "parent"
        app: menu = "@ menu/bottom_nav_menu" />
  <!-This frame layout is tentative. Replaced with home fragment with onCreate of MainActivity-><FrameLayout
        android: id = "@ + id/nav_host"
        android: layout_width = "match_parent"
        android: layout_height = "match_parent"
        app: layout_constraintHorizontal_bias = "0.0"
        app: layout_constraintLeft_toLeftOf = "parent"
        app: layout_constraintRight_toRightOf = "parent"
        android: layout_marginBottom = "70dp"></FrameLayout></androidx.constraintlayout.widget.ConstraintLayout>
class MainActivity: AppCompatActivity () {
   override fun onCreate (savedInstanceState: Bundle?) {
        super.onCreate (savedInstanceState)
        // Load the main screen
        setContentView (R.layout.activity_main)
        // Load the navigation part at the bottom of the page
        val navView: BottomNavigationView = findViewById (R.id.nav_view)
        // Immediately overwrite FlameLayout with the list of the first fragment "homeFragment"
        var homeFragment: HomeFragment = HomeFragment ()
        val fragmentManager = supportFragmentManager
        val transaction = fragmentManager.beginTransaction ()
        transaction.replace (R.id.nav_host, homeFragment)
        transaction.commit ()

The first home Fragment displayed is written as follows. The event listener part when the item of ListView is tapped is replaced with the next fragment "caregory" fragment.

class HomeFragment: Fragment () {
   override fun on CreateView (
        inflater: LayoutInflater,
        container: ViewGroup ?,
        savedInstanceState: Bundle?
    ): View? {
        val root = inflater.inflate (R.layout.list_view, container, false)
        return root
    override fun onViewCreated (view: View, savedInstanceState: Bundle?) {
        super.onViewCreated (view, savedInstanceState)
        // Load the data to be displayed in ListView
        val homeArray = resources.getStringArray (R.array.home_array)
        // Set ListView
        val adapter =
            this.context? .let {ArrayAdapter<String>(
            )}val listView: ListView = view.findViewById (R.id.listView) as ListView
        listView.adapter = adapter
        // Event listener when a row in listView is clicked
        listView.setOnItemClickListener {parent, view, position, id->          // Display the next fragment "Category Fragment"
            val fragmentManager: FragmentManager = childFragmentManager
            // Create Fragment Transaction from Fragment Manager
            val fragmentTransaction: FragmentTransaction = fragmentManager.beginTransaction ()
            // Create the Fragment that will be the following list
            val categoryFragment: Fragment = CategoryFragment ()
            // replace to the next fragment
            fragmentTransaction.replace (R.id.list, categoryFragment)
            // Add to backstack → Set to return to this activity when the back button of the terminal is pressed
            fragmentTransaction.addToBackStack (null)
            // Reflect the above changes
            fragmentTransaction.commit ()

In addition, "R.id.list" used in HomeFragment is described in the following XML file "list_view.xml".

        android: id = "@ + id/listView"
        android: layout_width = "match_parent"
        android: layout_height = "match_parent"
        android: layout_marginStart = "8dp"
        android: layout_marginTop = "8dp"
        android: layout_marginEnd = "8dp"

I haven't been able to move forward, and I would appreciate it if you could teach me.

  • Answer # 1

    Since the reproduction test cannot be performed only with the source file you provided, I only noticed it while looking at the source file.

    In MainActivity, the fragment is drawn in FrameLayout with ID nav_host, but in HomeFragment, it is trying to replace the ID that does not appear in the source file presented as R.id.list.

    This will keep the fragment drawn in nav_host as it is, which seems to be the reason why it looks like it is drawn twice. It's literally a replace, so you should replace the existing fragment in R.id.nav_host.

    Also, at this time, you will be working on the parent layout, so I think you have to get the FragmentManager with the parentFragmentManager.