I'm using the DrawerLayout with fragments inside and every fragment navigates to another fragment. I was able to handle the physical back button using :
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val callback = requireActivity().onBackPressedDispatcher.addCallback(this) {
findNavController().navigate(R.id.action_user_validation_to_make_money);
}
}
But every time that I go inside another fragment, the toolbar shows a back button :
I would like to know how can I handle that back button. Thanks!
To navigate using up button, as mentioned in the official docs, override onSupportNavigateUp() in your activity class
override fun onSupportNavigateUp(): Boolean {
return navController.navigateUp(drawerLayout)
}
Related
I want to implement a single activity project.
After showing splash i want to navigate to HomeFragment or LoginFragment based on user's login condition. In the MainActivity :
override fun onCreate(savedInstanceState: Bundle?) {
val splashScreen = installSplashScreen()
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
if (userLoggedIn()) {
navigateToHomeScreen()
} else {
navigateToLoginScreen()
}
}
The question is how should i set the navigation xml? Which one of the fragments should be the startDestionation. What's the best approach for a smooth splash/login( sign-in/sign-up/forget-pass)/ home flow.
the onBackPressed() in the signup page is okay and i put the same code in another activity and when i pressed it, the app will go back to previous activity but it will close first..
this is the code in my second activity which the app will close after i press the back arrow
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityAllusersignupBinding.inflate(layoutInflater)
setContentView(binding.root)
//action bar
actionBar = supportActionBar!!
actionBar.title = "User Registration"
actionBar.setDisplayHomeAsUpEnabled(true)
}
override fun onSupportNavigateUp(): Boolean {
onBackPressed()//go back to previous activity, when back button of actionbar clicked
return super.onSupportNavigateUp()
}
}
I have been meeting this issue now and then, how to make activity show back button an make it return to the parent activity without too much complexity.
Google have extensive documentation, but it is blown for someone who want a simple working approach. So am putting this question and answering it myself as rather documentation for others.
Enable the "Back" button with
supportActionBar?.setDisplayHomeAsUpEnabled(true)
Override onSupportNavigateUp to make it actually go back
override fun onSupportNavigateUp(): Boolean
{
onBackPressed()
return super.onSupportNavigateUp()
}
Here is the full code
class SomeChildActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_new_invoice)
supportActionBar?.setDisplayHomeAsUpEnabled(true)
}
override fun onSupportNavigateUp(): Boolean {
onBackPressed()
return super.onSupportNavigateUp()
}
}
In my main activity when user clicks button it shows him specific fragment. But if he clicks it again it adds another instance to backstack. And then the user needs to click back many times as click on the button.
class AppActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_app)
SharedPreferenceHelper.init(this)
GRPCClient.init(this)
DataBaseHelper.init(this)
imageViewDot.setOnClickListener {
findNavController(this, R.id.navHostFragmentApp).navigate(R.id.syncFragment)
}
}}
How can I prevent it from happening. What I need to do is if fragment is visible the button will not do anything.
try to flag that you already added this fragment and don't do that again
class AppActivity : AppCompatActivity() {
var navigated: Boolean = false
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_app)
SharedPreferenceHelper.init(this)
GRPCClient.init(this)
DataBaseHelper.init(this)
imageViewDot.setOnClickListener {
if(navigated) return
findNavController(this, R.id.navHostFragmentApp).navigate(R.id.syncFragment)
navigated = true
}
}
override fun onBackPressed() {
super.onBackPressed() // removes from back stack if present in there
navigated = false
}
}
or you can use getBackStackEntry or getCurrentBackStackEntry from NavController instance to check that this Fragment is already on the position
I use navigation component for navigating between my fragments. My app is simple. It has two fragmentsm the first one is list of items and the second one shows details of that Item. When user click on an item, I call
view.findNavController()
.navigate(R.id.action_photosFragment_to_photoDetailsFragment, bundle)
but problem is when I press back button, the first fragment reloads and make a network call again.
override fun onActivityCreated(savedInstanceState: Bundle?) {
photosViewModel.getPhotos()
photosViewModel.photosLiveData.observe(viewLifecycleOwner, photosObserver)
photosViewModel.loadingLiveData.observe(viewLifecycleOwner, loadingObserver)
super.onActivityCreated(savedInstanceState)
}
this block of code calls again! How can I stop reloading?
Use onCreate() in your fragment to call the network:
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
photosViewModel.getPhotos()
}