Meenakshi Khandelwal
Meenakshi Khandelwal

Reputation: 173

Android - Fragment called by Bottom navigation tabs is reloading every time

I am creating a project which uses bottom navigation. I am using fragment to make tabs call

val transaction = supportFragmentManager.beginTransaction()
transaction.add(R.id.frame_layout, Fragment1.newInstance(),Fragment1.newInstance().TAG)
transaction.addToBackStack(null).commit()

bottomNavigationView.setOnNavigationItemSelectedListener(object : BottomNavigationView.OnNavigationItemSelectedListener {

        override fun onNavigationItemSelected(item: MenuItem): Boolean {

            if(item.itemId == lastSelectedItemId){
                return true
            }

            var menuTag:String ?= null
            var selectedFragment: Fragment? = null
            lastSelectedItemId = item.itemId

            when (item.itemId) {
                R.id.tab1 -> {
                    selectedFragment = Fragment1.newInstance()
                    menuTag = selectedFragment.TAG
                }
                R.id.tab2 -> {
                    selectedFragment = Fragment2.newInstance()
                    menuTag = selectedFragment.TAG
                }
                R.id.tab3 -> {
                    selectedFragment = Fragment3.newInstance()
                    menuTag = selectedFragment.TAG
                }
                R.id.tab4 ->{
                    selectedFragment = Fragment4.newInstance()
                    menuTag = selectedFragment.TAG
                }
            }

            val transaction = supportFragmentManager.beginTransaction()
            transaction.replace(R.id.frame_layout, selectedFragment,menuTag)
            transaction.addToBackStack(menuTag).commit()
            return true
        }
    })

But Fragment always reload I tired some method

  1. replace().addToBackStack(null)
  2. replace().addToBackStack(tag)
  3. add, hide,show

addToBackStack() - using this, when i clicked android default bottom back button, its messing my layout of fragment. same with return@OnNavigationItemSelectedListener true

I followed many forum related this issue, but in my case nothing is working.

My forth fragment is

class Fragment4 : Fragment() {

var listOfMoreMenus = ArrayList<MoreLinksObject>()
var adapter: MoreLinksAdapter?=null
public var TAG: String = "more"
override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
}

override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
                          savedInstanceState: Bundle?): View? {
    val moreView = inflater.inflate(R.layout.fragment_more, container, false)
    val listView = moreView.findViewById(R.id.moreLinks) as ListView

    listOfMoreMenus.add(MoreLinksObject("test1","link1")) 
    listOfMoreMenus.add(MoreLinksObject("test2","link2")) 
    listOfMoreMenus.add(MoreLinksObject("test3","link3")) 
    listView.setNestedScrollingEnabled(true)
    adapter = MoreLinksAdapter(getActivity()!!,listOfMoreMenus)
    listView.adapter = adapter
    return moreView

}

companion object {
    fun newInstance(): Fragment4 {
        return Fragment4()
    }
}


inner class MoreLinksAdapter: BaseAdapter {

    var  listOfMoreMenus= ArrayList<MoreLinksObject>()
    var context: Context?=null
    constructor(context:Context, listOfMoreMenus: ArrayList<MoreLinksObject>):super(){
        this.listOfMoreMenus=listOfMoreMenus
        this.context=context

    }

    override fun getItem(position: Int): Any {
        return listOfMoreMenus[position]
    }

    override fun getItemId(position: Int): Long {
        return position.toLong()
    }

    override fun getCount(): Int {
        return  listOfMoreMenus.size
    }

    override fun getView(position: Int, convertView: View?, parent: ViewGroup?): View {
        val MoreLinkObj =  listOfMoreMenus[position]
        var inflator = context!!.getSystemService(Context.LAYOUT_INFLATER_SERVICE) as LayoutInflater
        var myView = inflator.inflate(R.layout.more_menu, null)
        val moreMenuName = myView.findViewById(R.id.moreMenuName) as TextView
        moreMenuName.text =  MoreLinkObj.name!!
        return myView
    }

}
}

Upvotes: 3

Views: 4593

Answers (1)

Levi Moreira
Levi Moreira

Reputation: 12007

Well, you're providing a new instance, calling newInstance() everytime, of each fragment everytime an option is selected. You have two options here:

1) Array of fragments

Keep your fragments in a global array when they're created and just reuse it

2) Tag

Add a tag to the fragment and use it to find the same fragment later.

As you're already setting the tags that's the best for you:

val FRAGMENT_1_TAG =  "FRAGMENT_1_TAG"
val FRAGMENT_2_TAG =  "FRAGMENT_2_TAG"
val FRAGMENT_3_TAG =  "FRAGMENT_3_TAG"
val FRAGMENT_4_TAG =  "FRAGMENT_4_TAG"

when (item.itemId) {
                R.id.tab1 -> {
                title = "Fragment1"
                selectedFragment = supportFragmentManager.findFragmentByTag(FRAGMENT_1_TAG);
                if (selectedFragment == null) {
                    selectedFragment = Fragment1.newInstance()
                }
                menuTag = FRAGMENT_1_TAG
                }
                R.id.tab2 -> {
                title = "Fragment2"
                selectedFragment = supportFragmentManager.findFragmentByTag(FRAGMENT_2_TAG);
                if (selectedFragment == null) {
                    selectedFragment = Fragment2.newInstance()
                }
                    menuTag = FRAGMENT_2_TAG
                }
                R.id.tab3 -> {
                title = "Fragment3"
                selectedFragment = supportFragmentManager.findFragmentByTag(FRAGMENT_3_TAG);
                if (selectedFragment == null) {
                    selectedFragment = Fragment3.newInstance()
                }
                    menuTag = FRAGMENT_3_TAG
                }
                R.id.tab4 ->{
                title = "Fragment4"
                selectedFragment = supportFragmentManager.findFragmentByTag(FRAGMENT_4_TAG);
                if (selectedFragment == null) {
                    selectedFragment = Fragment4.newInstance()
                }
                    menuTag = FRAGMENT_4_TAG
                }
            }

EDIT:

To clear the listview you can simply clear it before adding new content, therefore everytime onCreateView is called your list will be initialized from scratch:

listOfMoreMenus.clear()
listOfMoreMenus.add(MoreLinksObject("test1","link1")) 
listOfMoreMenus.add(MoreLinksObject("test2","link2")) 
listOfMoreMenus.add(MoreLinksObject("test3","link3")) 

As for changing the title, if your toolbar belongs to the activity you can set the title everytime you change fragments.(see above). If it belongs in the fragment then you need to change it in the onCreateView method so it will be changed everytime the fragment is changed.

Upvotes: 3

Related Questions