I am fetching data from network and showing in my list. I am using BottomNavigationView in Main Screen. It shows 4 tabs. When i launch the app, data is loading in Home screen but when i go to some other tab in Bottom navigation view and comeback to home tab, Data is not loading. In Home Screen has view pager tabs.
MainActivity.kt
class MainActivity : AppCompatActivity(), BottomNavigationView.OnNavigationItemSelectedListener {
lateinit var tabs: TabLayout
lateinit var toolbar: Toolbar
lateinit var sharedPreferences: SharedPreferences
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
sharedPreferences = getSharedPreferences(AppConstants.PREF_NAME, Context.MODE_PRIVATE)
toolbar = findViewById(R.id.toolbar)
setSupportActionBar(toolbar)
toolbar.setTitle(R.string.app_name)
val navigationView1: BottomNavigationView = findViewById(R.id.nav_view)
navigationView1.setOnNavigationItemSelectedListener(this)
if (savedInstanceState == null) {
loadFragment(MainFragment())
}
}
override fun onNavigationItemSelected(item: MenuItem): Boolean {
var fragment: Fragment? = null
when (item.itemId) {
R.id.news -> {
invalidateOptionsMenu()
fragment = MainFragment()
}
R.id.source -> {
fragment = SourcesFragment()
toolbar.getMenu().clear()
toolbar.setTitle("News Sources")
}
R.id.save -> {
toolbar.setTitle("Saved Articles")
toolbar.getMenu().clear()
fragment = WatchListFragment()
}
R.id.settings -> {
toolbar.setTitle("Settings")
toolbar.getMenu().clear()
fragment = SettingsFragment()
}
}
loadFragment(fragment)
return true
}
private fun loadFragment(fragment: Fragment?) {
val transaction = supportFragmentManager.beginTransaction()
.setCustomAnimations(R.anim.design_bottom_sheet_slide_in, R.anim.design_bottom_sheet_slide_out)
transaction.replace(R.id.container, fragment!!)
transaction.commit()
}
override fun onCreateOptionsMenu(menu: Menu?): Boolean {
menuInflater.inflate(R.menu.main, menu)
return true
}
override fun onOptionsItemSelected(item: MenuItem?): Boolean {
when (item?.itemId) {
R.id.action_search -> {
startActivity(Intent(this, SearchActivity::class.java))
}
else -> ""
}
return true
}
}
class MainFragment : Fragment() { lateinit var tabs: TabLayout lateinit var pager: ViewPager lateinit var adapter: PagerAdapter
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
var view = inflater.inflate(R.layout.fragment_main, container, false)
pager = view.findViewById(R.id.viewpager)
setupViewPager(pager)
pager.addOnPageChangeListener(onPageChangeListener)
tabs = view.findViewById(R.id.tabs)
tabs.setupWithViewPager(pager)
Log.d("LIVE", "onCreateView")
return view
}
private fun setupViewPager(pager: ViewPager) {
adapter = PagerAdapter(fragmentManager!!)
adapter.addFragment(TopNewsFragment(), "Top News")
adapter.addFragment(TechnologyFragment(), "Technology")
adapter.addFragment(BusinessFragment(), "Business")
adapter.addFragment(SportsFragment(), "Sports")
adapter.addFragment(EntertainmentFragment(), "Entertainment")
adapter.addFragment(ScienceFragment(), "Science")
adapter.addFragment(HealthFragment(), "Health")
pager.adapter = adapter
adapter.notifyDataSetChanged()
}
private val onPageChangeListener = object : ViewPager.OnPageChangeListener {
override fun onPageScrolled(position: Int, positionOffset: Float, positionOffsetPixels: Int) {
}
override fun onPageSelected(position: Int) {
adapter.notifyDataSetChanged()
}
override fun onPageScrollStateChanged(state: Int) {
}
}
}
fragment_main.xml
<FrameLayout 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">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<com.google.android.material.tabs.TabLayout
android:id="@+id/tabs"
style="@style/Widget.MaterialComponents.TabLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:elevation="10dp"
app:tabGravity="center"
app:tabIndicatorColor="@color/tab_selected_color"
app:tabMode="scrollable"
app:tabSelectedTextColor="@color/tab_selected_color"
app:tabTextColor="@color/textColorPrimary" />
<androidx.viewpager.widget.ViewPager
android:id="@+id/viewpager"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior" />
</LinearLayout>
</FrameLayout>
activity_main.xml
<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:id="@+id/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
tools:openDrawer="start">
<FrameLayout
android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior" />
<com.google.android.material.appbar.AppBarLayout
android:id="@+id/appbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:fitsSystemWindows="true"
android:theme="@style/AppTheme.AppBarOverlay"
app:elevation="10dp">
<androidx.appcompat.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
app:popupTheme="@style/AppTheme.PopupOverlay" />
</com.google.android.material.appbar.AppBarLayout>
<com.google.android.material.bottomnavigation.BottomNavigationView
android:id="@+id/nav_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom"
app:elevation="4dp"
app:itemIconTint="@drawable/bottom_navigation_text_color"
app:itemTextColor="@drawable/bottom_navigation_text_color"
app:labelVisibilityMode="labeled"
app:menu="@menu/bottom_navigation_menu" />
</androidx.coordinatorlayout.widget.CoordinatorLayout>
Updated Code:
class MainActivity : AppCompatActivity(), BottomNavigationView.OnNavigationItemSelectedListener {
lateinit var tabs: TabLayout
lateinit var toolbar: Toolbar
lateinit var sharedPreferences: SharedPreferences
private val mNewsFragment = MainFragment()
private val mSourceFragment: SourcesFragment = SourcesFragment()
private val mSaveFragment: WatchListFragment = WatchListFragment()
private val mSettingFragment = SettingsFragment()
var activeFragment: Fragment= MainFragment()
val fm: FragmentManager = supportFragmentManager
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
sharedPreferences = getSharedPreferences(AppConstants.PREF_NAME, Context.MODE_PRIVATE)
toolbar = findViewById(R.id.toolbar)
setSupportActionBar(toolbar)
toolbar.setTitle(R.string.app_name)
val navigationView1: BottomNavigationView = findViewById(R.id.nav_view)
navigationView1.setOnNavigationItemSelectedListener(this)
fm.beginTransaction().add(R.id.container, activeFragment).commit();
fm.beginTransaction().add(R.id.container, mSettingFragment).hide(mSettingFragment).commit();
fm.beginTransaction().add(R.id.container, mSourceFragment).hide(mSourceFragment).commit();
fm.beginTransaction().add(R.id.container, mSaveFragment).hide(mSaveFragment).commit();
/* if (savedInstanceState == null) {
val transaction = supportFragmentManager.beginTransaction()
.setCustomAnimations(R.anim.design_bottom_sheet_slide_in, R.anim.design_bottom_sheet_slide_out)
transaction.add(R.id.container, activeFragment).commit();
transaction.add(R.id.container, activeFragment).hide(activeFragment).commit();
transaction.add(R.id.container, activeFragment).hide(activeFragment).commit();
}*/
}
override fun onNavigationItemSelected(item: MenuItem): Boolean {
var fragment: Fragment? = null
when (item.itemId) {
R.id.news -> {
invalidateOptionsMenu()
fragment = MainFragment()
toolbar.getMenu().clear()
toolbar.setTitle("News Headlines")
}
R.id.source -> {
fragment = SourcesFragment()
toolbar.getMenu().clear()
toolbar.setTitle("News Sources")
}
R.id.save -> {
toolbar.setTitle("Saved Articles")
toolbar.getMenu().clear()
fragment = WatchListFragment()
}
R.id.settings -> {
toolbar.setTitle("Settings")
toolbar.getMenu().clear()
fragment = SettingsFragment()
}
}
loadFragment(fragment)
return true
}
private fun loadFragment(fragment: Fragment?) {
val transaction = supportFragmentManager.beginTransaction()
.setCustomAnimations(R.anim.design_bottom_sheet_slide_in, R.anim.design_bottom_sheet_slide_out).hide(activeFragment).show(fragment!!).commit();
activeFragment = fragment;
}
override fun onCreateOptionsMenu(menu: Menu?): Boolean {
menuInflater.inflate(R.menu.main, menu)
return true
}
override fun onOptionsItemSelected(item: MenuItem?): Boolean {
when (item?.itemId) {
R.id.action_search -> {
startActivity(Intent(this, SearchActivity::class.java))
}
else -> ""
}
return true
}
}
You need to Add
pager.setOffscreenPageLimit(2)
After
pager = view.findViewById(R.id.viewpager)
For details https://developer.android.com/reference/android/support/v4/view/ViewPager#setoffscreenpagelimit
UPDATE
As per new findings, when you swipe between fragments, your fragment state is saved.It is saved because when you swipe, Viewpager comes into action. And when you set pager.setOffscreenPageLimit(2), 2 fragments on either side are saved.Hence you have no issues with swiping.
But when you choose a fragment using BottomNavigationView, you are using replace. replace
method removes a fragment from a container so onCreate()
will get executed each time when user switches the tabs.
Using the following code for BottomNavigationView, you can solve this issue.
Bottom Line : Instead of Creating/replacing new fragments with BottomNavigationView, you can use hiding.
MainActivity
Declare a fragment variable like that
Fragment activeFragment= new MainFragment();
In onCreate, after setContentView, hide all fragments and commit them to the fragment manager, but do not hide the first fragment that will serve as home fragment.
fm.beginTransaction().add(R.id.main_container,fragment1).commit();
fm.beginTransaction().add(R.id.main_container, fragment2).hide(fragment2).commit();
fm.beginTransaction().add(R.id.main_container, fragment3).hide(fragment3).commit();
Replace your loadFragment() like that.
private fun loadFragment(fragment: Fragment?) {
val transaction = supportFragmentManager.beginTransaction()
.setCustomAnimations(R.anim.design_bottom_sheet_slide_in, R.anim.design_bottom_sheet_slide_out).hide(activeFragment).show(fragment).commit();
transaction.commit()
activeFragment=fragment;
}
2ND UPDATE
Replace
fm.beginTransaction().add(R.id.main_container,fragment1).commit();
With
fm.beginTransaction().add(R.id.main_container,activeFragment).commit();