Android BottomNavigationView with fragments
The following is an example for using BottomNavigationView alone with Fragments in Android. On each button click on the BottomNavigationView, the old fragment in the framelayout will be replaced by a new fragment.
navigation.xml, the menu for the bottom navigation bar.
activity_main.xml, the layout for the main activity, containing a framelayout for housing the fragments and a BottomNavigationView.
dashboard.xml, the layout file for the dashboard fragment. The layout files for favorites, home, notifications and settings are the same but with different text string in the TextView.
strings.xml, String resource file.
Button Navi Fragment Home Dashboard Notifications Favorites Settings
BaseActivity.kt, the base activity with activity life cycle callbacks for logging the callback calls.
import android.os.Bundle import android.support.v7.app.AppCompatActivity import android.util.Log abstract class BaseActivity : AppCompatActivity() { abstract val TAG : String abstract val LAYOUT_ID : Int override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) Log.d(TAG, "onCreate") setContentView(LAYOUT_ID) } override fun onRestart() { super.onRestart() Log.d(TAG, "onRestart") } override fun onStart() { super.onStart() Log.d(TAG, "onStart") } override fun onResume() { super.onResume() Log.d(TAG, "onResume") } override fun onPause() { super.onPause() Log.d(TAG, "onPause") } override fun onStop() { super.onStop() Log.d(TAG, "onStop") } override fun onDestroy() { super.onDestroy() Log.d(TAG, "onDestroy") } }
ABaseFrag.kl, the base fragment with fragment life cycle callbacks for logging callback calls.
import android.content.Context import android.os.Bundle import android.support.v4.app.Fragment import android.util.Log import android.view.LayoutInflater import android.view.View import android.view.ViewGroup abstract class ABaseFrag : Fragment() { abstract val TAG : String abstract val LAYOUT_ID : Int override fun onAttach(context: Context?) { super.onAttach(context) Log.d(TAG, "onAttach") } override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) Log.d(TAG, "onCreate") } override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { Log.d(TAG, "onCreateView") return inflater.inflate(LAYOUT_ID, container, false) } override fun onViewCreated(view: View?, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) Log.d(TAG, "onViewCreated") } override fun onActivityCreated(savedInstanceState: Bundle?) { super.onActivityCreated(savedInstanceState) Log.d(TAG, "onActivityCreated") } override fun onStart() { super.onStart() Log.d(TAG, "onStart") } override fun onResume() { super.onResume() Log.d(TAG, "onResume") } override fun onPause() { super.onPause() Log.d(TAG, "onPause") } override fun onStop() { super.onStop() Log.d(TAG, "onStop") } override fun onDestroyView() { super.onDestroyView() Log.d(TAG, "onDestroyView") } override fun onDestroy() { super.onDestroy() Log.d(TAG, "onDestroy") } override fun onDetach() { super.onDetach() Log.d(TAG, "onDetach") } }
MainActivity.kt, the main activity for initializing the fragments and bottom navigation bar.
import android.os.Bundle import android.support.design.widget.BottomNavigationView import android.util.Log import com.example.buttonnavifragment.fragments.* import kotlinx.android.synthetic.main.activity_main.* class MainActivity : BaseActivity() { override val TAG = MainActivity::class.java.simpleName override val LAYOUT_ID = R.layout.activity_main val FRAG_HOME = "home_frag" val FRAG_DASHBOARD = "dashboard_frag" val FRAG_NOTIFICATIONS = "notifications_frag" val FRAG_FAVORITES = "favorites_frag" val FRAG_SETTINGS = "settings_frag" private val mOnNavigationItemSelectedListener = BottomNavigationView.OnNavigationItemSelectedListener { item -> when (item.itemId) { R.id.navigation_home -> { loadFragByTag(FRAG_HOME) return@OnNavigationItemSelectedListener true } R.id.navigation_dashboard -> { loadFragByTag(FRAG_DASHBOARD) return@OnNavigationItemSelectedListener true } R.id.navigation_notifications -> { loadFragByTag(FRAG_NOTIFICATIONS) return@OnNavigationItemSelectedListener true } R.id.navigation_favorites -> { loadFragByTag(FRAG_FAVORITES) return@OnNavigationItemSelectedListener true } R.id.navigation_settings -> { loadFragByTag(FRAG_SETTINGS) return@OnNavigationItemSelectedListener true } } false } override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) navigation.setOnNavigationItemSelectedListener(mOnNavigationItemSelectedListener) BottomNavigationViewHelper.disableShiftMode(navigation) loadFragByTag(FRAG_HOME) } private fun loadFragByTag(tag : String) { var frag = supportFragmentManager.findFragmentByTag(tag) if (frag == null) { Log.d(TAG, "$tag not found, creating a new one.") when (tag) { FRAG_HOME -> { frag = HomeFrag() } FRAG_DASHBOARD -> { frag = DashboardFrag() } FRAG_NOTIFICATIONS -> { frag = NotificationsFrag() } FRAG_FAVORITES -> { frag = FavoritesFrag() } FRAG_SETTINGS -> { frag = SettingsFrag() } } } else { Log.d(TAG, "$tag found.") } supportFragmentManager .beginTransaction() .replace(R.id.fl_main, frag, tag) .commit() } }
HomeFrag.kt, the home fragment for showing home contents.
import com.example.buttonnavifragment.R class HomeFrag : ABaseFrag() { override val TAG = HomeFrag::class.java.simpleName override val LAYOUT_ID = R.layout.fragment_home }
BottomNavigationViewHelper.kt, a bottom navigation helper object for disabling the default shift behavior.
import android.support.design.internal.BottomNavigationItemView import android.support.design.internal.BottomNavigationMenuView import android.support.design.widget.BottomNavigationView import android.util.Log // https://stackoverflow.com/questions/40176244/how-to-disable-bottomnavigationview-shift-mode object BottomNavigationViewHelper { fun disableShiftMode(view: BottomNavigationView) { val menuView = view.getChildAt(0) as BottomNavigationMenuView try { val shiftingMode = menuView.javaClass.getDeclaredField("mShiftingMode") shiftingMode.isAccessible = true shiftingMode.setBoolean(menuView, false) shiftingMode.isAccessible = false for (i in 0 until menuView.childCount) { val item = menuView.getChildAt(i) as BottomNavigationItemView item.setShiftingMode(false) // set once again checked value, so view will be updated item.setChecked(item.itemData.isChecked) } } catch (e: NoSuchFieldException) { Log.e("BNVHelper", "Unable to get shift mode field", e) } catch (e: IllegalAccessException) { Log.e("BNVHelper", "Unable to change value of shift mode", e) } } }
Search within Codexpedia
Search the entire web