I'am want to save fragment with google map when i navigate by using bottom navigation bar, but if go to fragment A (for example) and back to MapFragment, in backstack will be added new MapFragment and it wiil make new request to google map api, that wasting time. i save the bundle but it's not what i want. How can i create one MapFragment and using it or maybe i should use other way?
#AndroidEntryPoint
class MainActivity : AppCompatActivity() {
private lateinit var navController: NavController
private lateinit var appBarConfiguration: AppBarConfiguration
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val navHostFragment = supportFragmentManager.findFragmentById(
R.id.navHostFragment
) as NavHostFragment
navController = navHostFragment.navController
// Setup the bottom navigation view with navController
val bottomNavigationView = findViewById<BottomNavigationView>(R.id.bottomNavigationView)
bottomNavigationView.setupWithNavController(navController)
appBarConfiguration = AppBarConfiguration(
setOf(R.id.mapFragment, R.id.eventsFragment, R.id.profileFragment)
)
setupActionBarWithNavController(navController, appBarConfiguration)
navController.addOnDestinationChangedListener { _, destination, _ ->
}
}
override fun onSupportNavigateUp(): Boolean {
return navController.navigateUp(appBarConfiguration)
}
}
#AndroidEntryPoint
class MapFragment : Fragment(R.layout.fragment_map) {
private var hasMapConfigured: Boolean = false
private lateinit var persistedMapBundle: Bundle
companion object {
private const val MAP_VIEW_BUNDLE_KEY = "mapview_bundle_key"
}
private val callback = OnMapReadyCallback { googleMap ->
val sydney = LatLng(-34.0, 151.0)
googleMap.addMarker(MarkerOptions().position(sydney).title("Marker in Sydney"))
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
persistedMapBundle = savedInstanceState?.getBundle(MAP_VIEW_BUNDLE_KEY) ?: Bundle()
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
val mapViewBundle = savedInstanceState?.getBundle(MAP_VIEW_BUNDLE_KEY)
initMapViewState(mapView, mapViewBundle)
mapView.getMapAsync(callback)
}
override fun onResume() {
super.onResume()
mapView?.onResume()
}
override fun onStart() {
super.onStart()
mapView?.onStart()
}
override fun onStop() {
super.onStop()
mapView?.onStop()
}
override fun onPause() {
super.onPause()
mapView?.onPause()
}
override fun onLowMemory() {
super.onLowMemory()
mapView?.onLowMemory()
}
override fun onSaveInstanceState(outState: Bundle) {
super.onSaveInstanceState(outState)
outState.putParcelable(MAP_VIEW_BUNDLE_KEY, persistedMapBundle)
outState.putBundle(MAP_VIEW_BUNDLE_KEY, persistedMapBundle)
}
override fun onDestroyView() {
super.onDestroyView()
mapView.onSaveInstanceState(persistedMapBundle)
mapView.onDestroy()
}
private fun initMapViewState(mapView: MapView, savedMapViewBundle: Bundle?) {
if (!persistedMapBundle.isEmpty) {
mapView.onCreate(persistedMapBundle)
hasMapConfigured = true
return
}
mapView.onCreate(savedMapViewBundle)
hasMapConfigured = savedMapViewBundle != null
}
}
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 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"
xmlns:map="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.google.android.gms.maps.MapView
android:id="#+id/mapView"
android:layout_width="match_parent"
android:layout_height="0dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:ignore="SpeakableTextPresentCheck,SpeakableTextPresentCheck" />
</androidx.constraintlayout.widget.ConstraintLayout>
Related
I'm learning android development, Im looking up information about navigation components and fragments but I havent understood what is the diferent between
NavigationUI.setupActionBarWithNavController(this,navHostFragment.navController) and setupActionBarWithNavController(navController,appBarConfig).
bellow you can find two codes, In one Im using NavigationUI but In the other I dont.
First one:
class MainActivity : AppCompatActivity() {
private lateinit var binding: ActivityMainBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding= ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
val navHostFragment = supportFragmentManager.findFragmentById(R.id.nav_host_fragment) as NavHostFragment
NavigationUI.setupActionBarWithNavController(this,navHostFragment.navController)
binding.bnNavBar.setupWithNavController(navHostFragment.navController)
}
override fun onSupportNavigateUp(): Boolean {
val navController = this.findNavController(R.id.nav_host_fragment)
return navController.navigateUp()
}
}
Second one:
class MainActivity : AppCompatActivity(), NavigationView.OnNavigationItemSelectedListener {
private lateinit var mainBinding: ActivityMainBinding
private lateinit var appBarConfiguration: AppBarConfiguration
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
mainBinding = ActivityMainBinding.inflate(layoutInflater)
setContentView(mainBinding.root)
val toolBar = mainBinding.activityMainContent.mainToolbar
//Setting up the tool bar as the app bar for the activity
setSupportActionBar(toolBar)
val host: NavHostFragment =
supportFragmentManager.findFragmentById(R.id.nav_host_fragment_container) as NavHostFragment
val navController = host.navController
//appBarConfiguration = AppBarConfiguration(navController.graph)
appBarConfiguration = AppBarConfiguration(
setOf(R.id.continentFragment),
mainBinding.drawerLayout
)
//First
setUpActionBar(navController,appBarConfiguration)
//Second
setUpNavigationView(navController)
}
private fun setUpActionBar(navController: NavController, appBarConfig : AppBarConfiguration) {
setupActionBarWithNavController(navController,appBarConfig)
}
private fun setUpNavigationView(controller: NavController) {
mainBinding.navView.setupWithNavController(controller)
}
override fun onNavigationItemSelected(item: MenuItem): Boolean {
mainBinding.drawerLayout.closeDrawer(GravityCompat.START)
return true
}
override fun onSupportNavigateUp(): Boolean {
val navController = findNavController(R.id.nav_host_fragment_container)
return navController.navigateUp(appBarConfiguration)|| super.onSupportNavigateUp()
}
override fun onBackPressed() {
if (mainBinding.drawerLayout.isDrawerOpen(GravityCompat.START)) {
mainBinding.drawerLayout.closeDrawer(GravityCompat.START)
} else {
super.onBackPressed()
}
}
}
Please, I'd be very thankful if someone can explain me the diference.
Ive read a lot about navigation but I havent found anything useful
I am new to Android Development. I like to show Bottom Sheet Dialog Fragment when I click one of the menu buttons at the Bottom Navigation View. When I click the favorite button on the languages, it shows empty for the bottom sheet dialog. Is there other way to do it? Thanks.
Main Activity
#AndroidEntryPoint
class MainActivity : AppCompatActivity() {
private lateinit var binding: ActivityMainBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
replacementFragment(HomeFragment())
binding.bottomNavigationView.setOnItemSelectedListener {
when (it.itemId) {
R.id.home -> replacementFragment(HomeFragment())
R.id.language -> replacementFragment(LanguageFragment())
// I cannot show the list on the fragment
R.id.favourite -> showFavouriteBottomFragment()
}
true
}
// val bottomSheetFragment = FavouriteFragment()
// bottomSheetFragment.show(supportFragmentManager, bottomSheetFragment.getTag() )
}
private fun replacementFragment(fragment: Fragment) {
val fragmentManager = supportFragmentManager
val fragmentTransaction = fragmentManager.beginTransaction()
fragmentTransaction.replace(R.id.fragmentContainerView, fragment)
fragmentTransaction.commit()
}
// I cannot get the following part to work....
private fun showFavouriteBottomFragment() {
val bottomSheetFragment = FavouriteFragment()
bottomSheetFragment.show(supportFragmentManager, bottomSheetFragment.getTag() )
}
}
Favourite Fragment
#AndroidEntryPoint
class FavouriteFragment: BottomSheetDialogFragment(){
private var _binding: FavouriteBottomSheetBinding ?= null
private val binding get() = _binding!!
private val viewModel: FavouriteViewModel by viewModels()
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
_binding = FavouriteBottomSheetBinding.inflate(inflater, container, false)
val view = binding.root
return view
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
// val binding = FavouriteBottomSheetBinding.bind(view)
val favouriteAdapter = FavouriteAdapter()
binding.apply {
favouriteLanguageList.apply{
adapter = favouriteAdapter
layoutManager = LinearLayoutManager(requireContext())
setHasFixedSize(true)
}
}
viewModel.favouriteLanguage.observe(viewLifecycleOwner){
favouriteAdapter.submitList(it)
}
}
}
Bottom Menu
<menu xmlns:tools="http://schemas.android.com/tools"
xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="#+id/home"
android:icon="#drawable/ic_baseline_home_24"
android:title="Home"
tools:ignore="HardcodedText" />
<item
android:id="#+id/favourite"
android:icon="#drawable/ic_baseline_favorite_24"
android:title="Favourite"
tools:ignore="HardcodedText" />
<item
android:id="#+id/language"
android:icon="#drawable/ic_baseline_language_24"
android:title="Language"
tools:ignore="HardcodedText" />
</menu>
AppModule
#Module
#InstallIn(SingletonComponent::class)
object AppModule {
#Provides
fun provideTestString() = "This is a string we will inject"
#Provides
#Singleton
fun provideDatabase(
app: Application,
callback: LanguageDatabase.Callback
) = Room.databaseBuilder(app, LanguageDatabase::class.java, "language_database")
.fallbackToDestructiveMigration()
.addCallback(callback)
.build()
#Provides
fun provideLanguageDao(db: LanguageDatabase) = db.languageDao()
#ApplicationScope
#Provides
#Singleton
fun provideApplicationScope() = CoroutineScope(SupervisorJob())
}
#Retention(AnnotationRetention.RUNTIME)
#Qualifier
annotation class ApplicationScope
Favourite Adapter
class FavouriteAdapter : ListAdapter<Language, FavouriteAdapter.FavouriteViewAHolder>(DiffCallback()) {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): FavouriteViewAHolder {
val binding = ItemFavouriteBinding.inflate(LayoutInflater.from(parent.context), parent, false)
return FavouriteViewAHolder(binding)
}
override fun onBindViewHolder(holder: FavouriteViewAHolder, position: Int) {
val currentItem = getItem(position)
holder.bind(currentItem)
}
inner class FavouriteViewAHolder(private val binding: ItemFavouriteBinding) : RecyclerView.ViewHolder(binding.root){
fun bind(language: Language){
binding.apply {
rbIsClicked.isChecked = language.isChecked
tvFavouriteLanguage.text = language.language
}
}
}
class DiffCallback : DiffUtil.ItemCallback<Language>() {
override fun areItemsTheSame(oldItem: Language, newItem: Language) =
oldItem.id == newItem.id
override fun areContentsTheSame(oldItem: Language, newItem: Language) = oldItem == newItem
}
}
Favourite View Model
#HiltViewModel
class FavouriteViewModel #Inject constructor(
private val languageDao: LanguageDao,
) : ViewModel() {
val favouriteLanguage = languageDao.getFavouriteLanguageByName().asLiveData()
}
Preferences Manager
private const val TAG = "PreferencesManager"
private val Context.dataStore by preferencesDataStore("user_preferences")
enum class SortOrder { BY_NAME}
data class FilterPreferences(val sortOrder: SortOrder, val hideSelectedLanguage: Boolean, val selectedLanguage: String)
#Singleton
class PreferencesManager #Inject constructor(#ApplicationContext context: Context){
private val dataStore = context.dataStore
val preferencesFlow = dataStore.data
.catch { exception ->
if(exception is IOException){
Log.e(TAG, "Error reading preferences", exception)
emit(emptyPreferences())
}else{
throw exception
}
}
.map{ preferences ->
val sortOrder = SortOrder.valueOf(
preferences[PreferencesKeys.SORT_ORDER] ?:SortOrder.BY_NAME.name
)
val hideSelectedLanguage = preferences[PreferencesKeys.HIDE_SELECTED_LANGUAGE] ?: false
val selectedLanguage = preferences[PreferencesKeys.SELECTED_LANGUAGE]?: "English"
FilterPreferences(sortOrder, hideSelectedLanguage, selectedLanguage)
}
suspend fun updateSortOrder(sortOrder: SortOrder){
dataStore.edit { preferences ->
preferences[PreferencesKeys.SORT_ORDER] = sortOrder.name
}
}
suspend fun updateHideSelectedLanguage(hideSelectedLanguage: Boolean){
dataStore.edit { preferences ->
preferences[PreferencesKeys.HIDE_SELECTED_LANGUAGE] = hideSelectedLanguage
}
}
suspend fun updateSelectedLanguage(selectedLanguage: String){
dataStore.edit{ preferences ->
preferences[PreferencesKeys.SELECTED_LANGUAGE] = selectedLanguage
}
}
private object PreferencesKeys{
val SORT_ORDER = stringPreferencesKey("sort_order")
val HIDE_SELECTED_LANGUAGE = booleanPreferencesKey("hide_selected_language")
val SELECTED_LANGUAGE = stringPreferencesKey("selected_language")
}
}
I have a Language Fragment which looks similar to Favourite Fragment.
I find a temporary solution...but I still have a bug as I have the press the favourite button twice to show a list in the BottomSheetDialogFragment.
Is there a way, I can solve the problem? The first time I press the favourite button it doesn't shows a BottomSheetDialog fragment.... I have to press it again to show the list.
KC
In the MainActivity, I declare the class favouriteFragment.
class MainActivity : AppCompatActivity() {
private lateinit var binding: ActivityMainBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// declare the favroute fragment.
val favouriteFragment = FavouriteFragment()
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
replacementFragment(HomeFragment())
binding.bottomNavigationView.setOnItemSelectedListener {
when (it.itemId) {
R.id.home -> replacementFragment(HomeFragment())
R.id.language -> replacementFragment(LanguageFragment())
R.id.favourite ->
// Pass the instace in the function.
showFavouriteBottomFragment(favouriteFragment)
}
true
}
In the function in Main Activity
private fun showFavouriteBottomFragment(favouriteFragment: FavouriteFragment) {
favouriteFragment.show(supportFragmentManager, favouriteFragment.tag)
}
I remove "setHasFixedSize(true)" and it can load the first time when I press the favorite button.
In my project that makes open new fragment with NavigationComponenet when click button. I want to test if fragment open when click button, But it don't work properly. Only it click button and does not open another fragment. So, I can't test if it works. Why it does not navigate?
#RunWith(AndroidJUnit4::class)
class WelcomeFragmentTestDoctor {
val phoneHelper = PhoneHelper
private lateinit var scenario: FragmentScenario<WelcomeFragment>
#Before
fun setup() {
scenario = launchFragmentInContainer(themeResId = R.style.AppTheme)
scenario.moveToState(Lifecycle.State.STARTED)
Intents.init()
}
#After
fun tearDown(){
Intents.release()
}
#Test
fun clickApplyAsADoctor(){
val navController = TestNavHostController(
ApplicationProvider.getApplicationContext())
scenario.onFragment { fragment ->
navController.setGraph(R.navigation.auth_navigation)
Navigation.setViewNavController(fragment.requireView(), navController)
}
onView(withId(R.id.buttonDoctor)).perform(click())
Assert.assertEquals(navController.currentDestination?.id, R.id.action_welcomeFragment_to_doctorRegistrationFragment)
}
}
fragment_doctor_registration.xml
<?xml version="1.0" encoding="utf-8"?>
<layout 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">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.constraintlayout.widget.ConstraintLayout
android:id="#+id/toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingTop="#dimen/_14sdp"
android:paddingBottom="#dimen/_14sdp"
app:layout_constraintTop_toTopOf="parent">
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.core.widget.NestedScrollView>
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>
DoctorRegistrationFragment.kt
class DoctorRegistrationFragment : Fragment() {
private lateinit var mBinding: FragmentDoctorRegistrationBinding
private val mViewModel: DoctorRegistrationViewModel by inject()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
}
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
mBinding = FragmentDoctorRegistrationBinding.inflate(inflater, container, false)
return mBinding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
DoctorRegistrationComponent.inject()
with(mBinding) {
backButton.setOnCrashOnClickListener {
findNavController().popBackStack()
}
btnSend.setOnCrashOnClickListener {
mViewModel.onEvent(
DoctorRegistrationInteractions.RegisterStart(fdr_name.text, fdr_surname.text,
fdr_title.text, fdr_diploma.text, fdr_branch.text,
inputLogin.lifEdittext.text.toString(), fdr_email.text, fdr_address.text,
fdr_company.text, fdr_tax.text
))
}
}
with(mViewModel) {
actions.map { it.getContentIfNotHandled() }.onEach(::handleActions).launchIn(viewLifecycleOwner.lifecycleScope)
}
}
private fun handleActions(action: DoctorRegistrationActions) {
when (action) {
is DoctorRegistrationActions.ErrorMessage -> PopupMessage.error(requireActivity(),message = action.message)
DoctorRegistrationActions.Init -> { }
is DoctorRegistrationActions.SuccessMessage -> {
PopupMessage.success(requireActivity(), message = action.message)
findNavController().popBackStack()
}
}
}
}
You need to check the fragment id not the Action id
Assert.assertEquals(navController.currentDestination?.id, R.id.doctorRegistrationFragment)
Assuming that doctorRegistrationFragment is the id of your fragment tag in your nav graph
<fragment
android:id="#+id/doctorRegistrationFragment"
/* rest of attrs */ >
I'm using Navigation Component, although I don't think that's the problem. The thing is that when I'm in a fragment that contains a ViewPager and I navigate to another one, when I go back using the back button or the gesture of the mobile phone, it returns to the previous fragment but it stops showing the ViewPager. I'll leave you my code for that fragment:
class HomeFragment : Fragment() {
private lateinit var homeFragmentViewModel: HomeFragmentViewModel
private var listAdapter: FlagsListAdapter? = null
private var regionName: String? = null
private val hashtagLabel: TextView by lazy { home_fragment__label__hashtag }
private val flagViewPager: ViewPager by lazy { home_fragment__viewpager__countries }
private val countryLabel: TextView by lazy { home_fragment__label__country_name }
private val showCasesButton: Button by lazy { home_fragment__button__country_cases }
companion object {
fun newInstance(): HomeFragment {
return HomeFragment()
}
}
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
return inflater.inflate(R.layout.fragment_home, container, false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
homeFragmentViewModel = ViewModelProvider(this).get(HomeFragmentViewModel::class.java)
homeFragmentViewModel.getCountriesFlagLiveData().observeOnce(viewLifecycleOwner, Observer {
setFlagsAdapter(it)
})
showCasesButton.setOnClickListener {
val actionNavigateToShowCasesFragment = HomeFragmentDirections.navigateHomeFragmentToShowCasesFragment()
regionName?.let { regionName -> actionNavigateToShowCasesFragment.regionName = regionName }
it.findNavController().navigate(actionNavigateToShowCasesFragment)
}
setFormatHashtag()
}
private fun setFlagsAdapter(flagModelList: List<FlagModel>) {
listAdapter = context?.let {
FlagsListAdapter(
flagModelList,
it
)
}
flagViewPager.adapter = listAdapter
flagViewPager.setPadding(130, 0, 130, 0)
flagViewPager.addOnPageChangeListener(object : ViewPager.OnPageChangeListener {
override fun onPageScrollStateChanged(state: Int) {
Toast.makeText(GlobalApplication.getContextFromApplication, "Hola", Toast.LENGTH_SHORT).show()
}
override fun onPageScrolled(
position: Int,
positionOffset: Float,
positionOffsetPixels: Int
) {
countryLabel.text = ""
countryLabel.text = flagModelList[position].regionName
regionName = flagModelList[position].regionName
}
override fun onPageSelected(position: Int) {
countryLabel.text = flagModelList[position].regionName }
})
}
private fun setFormatHashtag() {
val text = getString(R.string.home_fragment_hashtag)
val spannableString = SpannableString(text)
val foregroundColorSpan = context?.let {
ForegroundColorSpan(ContextCompat.getColor(it, R.color.hashtagColor))
}
spannableString.setSpan(foregroundColorSpan, 0, 8, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)
hashtagLabel.text = spannableString
}
}
This is my activity:
class MainActivity : AppCompatActivity() {
private val navigationBottomBar by lazy { activity_main__navigation_view__bottom_bar }
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
setUpNavigation()
}
private fun setUpNavigation() {
val navController = Navigation.findNavController(this, R.id.activity_main__graph__nav_host)
NavigationUI.setupWithNavController(navigationBottomBar, navController)
}
}
When you load the fragment the first time it is shown like this, which is how it should be shown, and if I use the Bottom Navigation View it does well too:
But when I use the back button on my phone, here's what happens:
The problem is in your HomeFragment,setFlagsAdapter(it)` doesn't get called when you come back to this fragment. Either
change observeOnce to observe
or
Move
homeFragmentViewModel.getCountriesFlagLiveData().observeOnce(viewLifecycleOwner, Observer {
setFlagsAdapter(it)
})
from onCreateView to
override fun onResume(){
super.onResume()
homeFragmentViewModel.getCountriesFlagLiveData().observeOnce(viewLifecycleOwner, Observer {
setFlagsAdapter(it)
})
}
I'm new to android and working through some tutorials. Currently working on implementing the Navigation controller and overriding the up button functionality. Part of doing this is to link the action bar with the Nav controller and overriding onSupportNavigateUp(). In doing this I noticed that we have to fetch the Nav Controller by id twice so I decided to create a class variable that does this and re-use the variable. The problem is the App crashes on startup when I do this. My guess is this is because I'm trying to get the Nav Controller before inflating the views?
So my question is why does this work:
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
#Suppress("UNUSED_VARIABLE")
val binding = DataBindingUtil.setContentView<ActivityMainBinding>(this, R.layout.activity_main)
val navController = this.findNavController(R.id.myNavHostFragment)
NavigationUI.setupActionBarWithNavController(this, navController)
}
override fun onSupportNavigateUp(): Boolean {
val navController = this.findNavController(R.id.myNavHostFragment)
return navController.navigateUp()
}
}
But this doesn't work:
class MainActivity : AppCompatActivity() {
private val navController = this.findNavController(R.id.myNavHostFragment)
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
#Suppress("UNUSED_VARIABLE")
val binding = DataBindingUtil.setContentView<ActivityMainBinding>(this, R.layout.activity_main)
NavigationUI.setupActionBarWithNavController(this, navController)
}
override fun onSupportNavigateUp(): Boolean {
return navController.navigateUp()
}
}
You are right, you are assigning the navController before the view is inflated and passed the null to setupActionBarWithNavController
You can do it like this,
class MainActivity : AppCompatActivity() {
private lateinit var navController: NavController
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
#Suppress("UNUSED_VARIABLE")
val binding = DataBindingUtil.setContentView<ActivityMainBinding>(this, R.layout.activity_main)
NavigationUI.setupActionBarWithNavController(this, navController)
navController = this.findNavController(R.id.myNavHostFragment)
}
override fun onSupportNavigateUp(): Boolean {
return navController.navigateUp()
}
}