I am using native Fragments and a fragment transaction with add() and hide(). When I go back to the original fragment with the back button, the ripple animation from android:background="?attr/selectableItemBackground" resumes from when I opened the fragment originally. How do I cancel an animation when hiding a fragment in a transaction?
getFragmentManager().beginTransaction()
.hide(this)
.add(R.id.fragment_container, fragment)
.addToBackStack(null)
.commit()
Edit:
I am changing my app to use ViewPager.
Related
I've got some problems understanding Fragments in Android.
The bottom navigation of my MainActivity has got three items: FragmentA, FragmentB, FragmentC.
FragmentC has got a button. When the user clicks that button, another FragmentD should display additional information.
FragmentD should have an up-button in the toolbar. When the user clicks on that button, he gets back to FragmentC.
When the user selects a different fragment from the navigation, FragmentD should disappear.
Inside the onClick of my button I've tried to use this
FragmentManager manager = requireActivity().getSupportFragmentManager();
FragmentTransaction transaction = manager.beginTransaction();
transaction.replace(R.id.nav_host_fragment, new FragmentD());
transaction.addToBackStack(null);
transaction.commit();
with nav_host_fragment being the fragment container for the bottom navigation items of my MainActivity.
Why doesn't transaction.replace replace FragmentC with FragmentD? When I press the button, FragmentD appears above FragmentC and has got a transparent background. FragmentD also does not get replaced by the other fragments when I select a different item from the bottom navigation. Is it because I'm using the nav_host_fragment container for FragmentD?
How do I get the up-button?
The solution is to use Navigation instead of FragmentTransaction.
In the Navigation xml file I've added FragmentD and an action for FragmentC with FragmentD as destination. In the button's onClick I now call Navigation.findNavController(view).navigate(R.id.fragment_c_to_fragment_d);
To make the button work, I had to override onSupportNavigateUp:
#Override public boolean onSupportNavigateUp() {
return Navigation.findNavController(this, R.id.main_fragment).navigateUp() ||
super.onSupportNavigateUp(); }
I'm using shared element transition between two fragments. The animation works well, but there is a white flash which happens in the fragment.
In my first fragment, I set shared element transition using:
getActivity().getSupportFragmentManager()
.beginTransaction()
.addSharedElement(ivPic, ViewCompat.getTransitionName(ivPic))
.addToBackStack(null)
.replace(R.id.fragment_container, fragment)
.commit();
And in my second fragment inside onCreate():
Transition transition = TransitionInflater.from(getContext()).inflateTransition(R.transition.shared_element_transition);
setSharedElementEnterTransition(transition);
setSharedElementReturnTransition(transition);
Things I've tried:
setEnterTransition(null) in my second fragment
setCustomAnimations(0, 0) in fragment transition in first fragment
Running a simple slide to the left animation for both entering and existing fragment produces the effect of the entering fragment slightly overlapping with the exit fragment. This leads me to think that both transition are not executed at the same time. Any clue or confirmation of this behavior?
The desired effect is to slide the fragments to the left at the same time, without overlap.
The code:
Fragment current = ...;
Fragment fragment = ...;
Transition slideIn = TransitionInflater.from(this)
.inflateTransition(R.transition.fragment_indicator_enter)
.setDuration(300)
.setInterpolator(new LinearInterpolator());
fragment.setEnterTransition(slideIn);
currentFragment.setExitTransition(TransitionInflater.from(this)
.inflateTransition(R.transition.fragment_indicator_exit)
.setDuration(300)
.setInterpolator(new LinearInterpolator()));
getSupportFragmentManager()
.beginTransaction()
.replace(R.id.fragment_container, fragment)
.addToBackStack(null)
.commit();
The only workaround by know it has been to add a setStartDelay(30) for the entering transition. But weird thing, I have different transitions for different fragments and the startDelay has to be different to produce the effect of both fragment sliding to the left at the same time.
The effect is an expected behavior of the transition, as all the views in the layout are moved at a different time to avoid moving everything as a block a create some natural sense of motion. I intentionally want this block effect, so it's solved by adding a target for the transition, where this target is the FrameLayout containing the views of the fragment.
fragment.setEnterTransition(new Slide(Gravity.RIGHT)
.addTarget(R.id.whole_content));
Did you try placing the animations directly in the transaction call?
getSupportFragmentManager()
.setCustomAnimations(R.transition.fragment_indicator_enter, R.transition.fragment_indicator_exit)
.beginTransaction()
.replace(R.id.fragment_container, fragment)
.addToBackStack(null)
.commit();
I have 2 fragments the first contains a button which on clicked opens a fragment with a ListView in it. I have a shared element transition for the button to transition into the new fragment (root layout) but I would also like to have this transition in reverse (the list fragment contracts into the button again).
However currently I detect the list item click and send an event to the Activity which pops the listview fragment off the backstack (popBackStackImmediate()) hence does not show the transition.
Is there a good way to allow back navigation while preserving reverse transition to work as well?
did you try this:
FragmentManager fm = getSupportFragmentManager();
fm.popBackStack();
fm.executePendingTransactions();
PS: use getSupportFragmentManager() if you're using the support library else use getFragmentManager().
I have an Activity with navigation drawer and a default fragment set in to Activity when application starts.
I have 4 top level navigation in my navigation drawer
Fragment 1
Fragment 2
Fragment 3
Fragment 4
and switching the fragments inside the activity on click on each each navigation. I want implement the fragment navigation in such manner that from each top level navigation fragment, if user clicks back button it should first come to Main or default fragment and from there app should exit same like in Google Play. I call it master fragment.
eg:
Default(master) Fragment > Fragment 1
Fragment > Fragment 2
Fragment 2 -- Back pressed > Deafult fragment and like so.
What I have tried so far :
I have tried adding fragment in backstack but it doesn't help it takes me all fragment in stack.
getSupportFragmentManager().beginTransaction()
.add(R.id.container, selectedFragment)
.addToBackStack("naviagtion_stack")
.commit();
My each top fragments also have child fragments in stack so stack count also did not help me.
I don't want to remove and add my default fragment because as it fetches some data from network so recreation will make the network call again which i don't want .
I want exactly what Google Play does. I just want to know the logic.
Add your master fragment to backstack and remember the tag: fragmentManager.beginTransaction()
.add(R.id.main_layout, masterFragment)
.addToBackStack(INITIAL_STATE)
.commit();
Click on the navigation elements should do following before adding a corresponding fragment: fragmentManager.popBackStack(INITIAL_STATE, 0);
This call removes from backstack everything but your master fragment.
All fragment transactions (including navigation fragments) should generally do the same thing, for example:
fragmentManager.beginTransaction()
.add(R.id.main_layout, fragment)
.addToBackStack(null)
.commit();