Current situation:
There is only one activity called MainActivity.
MainActivity maintains the NavHostFragment.
There is a WebViewFragment which embeded a WebView inside.
Thera are many other fragment controlled by NavHostFragment.
What troubles me:
I can forward web pages inside WebView, but when I press back to go back inside the WebView, the NavController handle's it, pop the fragment away.
Since the WebView is inside a fragment not an activity, which means there is not method called onBackPressed() to override.
Reference:
See NavigationBasicSample#github
See Getting start with Navigation#android developer home
As far as I understand, you need a way to handle onBackPressed on your fragment, right? With NavigationComponent you can do it like this, in your onViewCreated:
requireActivity().onBackPressedDispatcher.addCallback(viewLifecycleOwner, object : OnBackPressedCallback(true) {
override fun handleOnBackPressed() {
if (mWebView.canGoBack()) {
mWebView.goBack();
} else {
findNavController().popBackStack(R.id.dest, false)
}
}
})
add a new fragment and inside that place your WebView ,using navigation editor navigate from WebViewFragment to new fragment ,in the right hand side of navigation editor you can see an option to backstack option to manage .
code lab has example https://codelabs.developers.google.com/handling-gesture-back-navigation#5 you need onBackPressedDispatcher which need to be enabled and disabled.
you can use mWeb.goBack(); to goBack to the previous page or for returning back.
Related
I have two fragments; HomeFragment & NextFragment and I go to the next one with a button from the base fragment. Then via back press I want to go back to the first one, however I end up at the apps home screen. A solution
requireActivity().onBackPressedDispatcher
.addCallback(viewLifecycleOwner, object : OnBackPressedCallback(true) {
override fun handleOnBackPressed() {
findNavController().popBackStack()
}
})
was given here but it did not work. I am using ViewPager2 and saw that the home fragment is destroyed when I go to the next one. How can I solve the problem?
private fun navBottomClick() {
bottomNavigationView?.setOnItemSelectedListener {
when(it.itemId){
R.id.workout ->{
val fragmentTransaction:FragmentTransaction = supportFragmentManager.beginTransaction()
fragmentTransaction.replace(R.id.container,WorkoutFragment(),"WORKOUT")
//fragmentTransaction.addToBackStack("WORKOUT")
fragmentTransaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE)
fragmentTransaction.commit()
}
R.id.steps ->{
intent = Intent(this,StepsActivity::class.java)
startActivity(intent)
}
}
true
}
}
override fun onBackPressed() {
super.onBackPressed()
}
}
When I pressed back, my app is closed. I want to make it go from a fragment to the main acitvity.
You have misunderstood the concept of Fragments and Activity . The issue you facing of the application getting close on navigating back from the fragment because it is the last fragment present in the stack .
Concept :
Basically , an Activity acts as an container for all of your Fragments . So , you create an activity and create a Fragment-Container / FrameLayout in that Activity wherein you assign the Fragments. So , Consider this example :
Here you can see, there are two fragments and both of them are placed in only one Activity . So this clarifies that Activity acts as an container for fragments .
What causes the Issue of Application being closed :
So what happens is when you navigate back from the last fragment , since it does not have anywhere to go back it closes the application .
Solution :
So if you want to get your Activity on navigating back on the last fragment to the Activity then , you need to override the popBackStack() method on the last Fragment and in there you need to disable the FragmentContainer / FrameLayout view, in this way you can get your activity back .
Recommended Solution : Move all the stuffs that you want to show at the end from your Activity to another Fragment and popBackStack() to that Fragment, doing such maintains the Single Activity principle .
You should have a popbackstack to send the screen correctly. Check if your fragment has implemented inside of this activity, if yes, really that will be closed.
Don't forget that fragment is inside of the one activity.
You need to un-comment this line
//fragmentTransaction.addToBackStack("WORKOUT")
then it will work as there is no stack maintained activity can't go back to previous fragment and will close the activity.
I have three fragments A, B and C. And I'm using navHostFragment container in MainActivity. So the application goes from A -> B using kotlin extension function findNavController().navigate... and then go from B to C using same function. All works fine till here.
Now in Fragment C, I'm replacing different elements on fragment C using
activity?.supportFragmentManager
?.beginTransaction()
?.replace(R.id.list_container, someFragment)
?.addToBackStack("some_frag_id")
?.commit()
The list_container is replaced with someFragment. After this when I press physical back button Fragment C pops out and my app goes to Fragment B while what I expect it to restore replaced list_container i.e. whatever was there before replacement.
I'm also overiding this in my MainActivity
override fun onBackPressed() {
val count = supportFragmentManager.backStackEntryCount
if (count == 0) {
super.onBackPressed()
//additional code
}
else {
supportFragmentManager.popBackStack()
}
}
I'm not sure what is missing here. I have read a lot of solutions on stackoverflow but none worked to my satisfaction. Please guide.
If you are adding a Fragment to a View within a Fragment, you must always use the childFragmentManager - using activity?.supportFragmentManager is always the wrong FragmentManager to use in that case.
Besides fixing cases with restoring state (which would not work when using the wrong FragmentManager), this also ensures that the default behavior for dispatching onBackPressed() down the FragmentManager hierarchy will work out the box - you should not need any logic at all in onBackPressed() to have the pop work correctly.
If you need to intercept the back button in Fragment C, you should follow the providing custom back documentation to register an OnBackPressedDispatcher - you should not override onBackPressed() even in those cases.
I have three fragments in the MainActivity, i.e Home, Search and More. On backpressed in the More and Search fragments, I want to go to the Home fragment irrespective of the Backstack.
Implement a navigation component and use a global action to move back to the main fragment.
For more info, have a look at Android's latest documentation on Navigation Components
You must implement an intention among the fragments within onBackStack (this if you made the FragmentManager correctly), where whenever pressed, the new intent that will be opened will be from Fragment Home, don't forget to clean the previous intent with
intent.addFlags (Intent.FLAG_ACTIVITY_CLEAR_TOP);
intent.addFlags (Intent.FLAG_ACTIVITY_NEW_TASK);
You can override onbackpress and navigate to home fragment.
Code for overriding backpress from fragment
val callback: OnBackPressedCallback =
object : OnBackPressedCallback(true) {
override fun handleOnBackPressed() {
// Your code here
}
}
requireActivity().onBackPressedDispatcher.addCallback(viewLifecycleOwner, callback)
I want to implement the onbackpressed() in android and my code is as follows
public void backpressed(){
NDListeningFragment fragment1=(NDListeningFragment)getSupportFragmentManager().findFragmentByTag(ConnectedDevicesFragment.TAG);
if(fragment1!=null && fragment1.isVisible())
{
super.onBackPressed();
}
else
{
fragment1=(NDListeningFragment)SimpleFragmentFactory.createFragment(ConnectedDevicesFragment.TAG);
getSupportFragmentManager().beginTransaction().replace(R.id.content,fragment1).commit();
fragment1.setUserVisibleHint(true);
}
}
The above code checks if the visible fragment is ConnectedDevicesFragment. If yes then super() is called and if not then I create ConnectedDevicesFragment and replace it in the framelayout.
But I am not able to implement in this way. When I press back button it reloads the Connected DevicesFragment again and again.
can you help with some workaround.
Cheers!
You creates fragment1 object every time in the onBackPressed function it means it will not null and it is on invisible state. You need to add NDListeningFragment in backstack when you open NDListeningFragment first and check Is the fragment available in back stack. If yes then call super.onBackpressed.