Home>

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.

problem

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>(
                it,
                android.R.layout.simple_list_item_1,
                homeArray
            )}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".

<ListView
        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"
        ></ListView></androidx.constraintlayout.widget.ConstraintLayout>

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.