I am trying to implement app with navigation drawer.
I created application on Eclipse.
This is default(or template) navigation drawer application.
MainActivity has root FrameLayout which includes different fragments at different times.
By default, it contains fragment A.
When item B will be chosen from navigation drawer, it will replace fragment A to fragment B.
MainActivity:
FragmentTransaction transaction = fragmentManager.beginTransaction();
transaction.replace(R.id.container, fragmentB);
transaction.addToBackStack(null);
transaction.commit();
FragmentB is root fragment for fragmentB2, FragmentB3 etc.
I thought that in this way, it will be easier to save fragments state.
It is saving fragment state only for FragmentB2.
FragmentA(root A) onCreateView():
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
/* Inflate the layout for this fragment */
View view = inflater.inflate(R.layout.fragment_balance_root, container,
false);
FragmentTransaction transaction = getChildFragmentManager()
.beginTransaction();
transaction.replace(R.id.balance_root_frame, MainActivity.balanceMainFragment);
transaction.addToBackStack(null);
transaction.commit();
return view;
}
FragmentA2 OnCreateView():
View rootView = inflater.inflate(R.layout.fragment_balance_main,
container, false);
return rootView;
FragmentB(root B) onCreateView():
FragmentTransaction transaction = getChildFragmentManager()
.beginTransaction();
transaction.replace(R.id.tariffs_root_frame, MainActivity.tariffsMainFragment);
transaction.addToBackStack(null);
transaction.commit();
FragmentB2:
private static void goToTariffInfo() {
FragmentTransaction transaction = fragmentManager.beginTransaction();
transaction.replace(R.id.tariffs_root_frame, new TariffsInfoFragment());
transaction.addToBackStack(null);
transaction.commit();
}
Fragment B3:
View rootView = inflater.inflate(R.layout.fragment_tariffs_info,
container, false);
return rootView;
I have many questions, but they are related to each other.
1. How to avoid saving root fragment in backstack?
When I press back button on Fragment A2 it goes to A1 which is blank.
I have tried to remove addToBackStack from MainActivity. This caused to quit on only one press back button.
I have tried to remove addToBackStack from FragmentA. No effect.
2.How to set seperate backstack for different collections of fragments?
For example: Navigation drawer includes 2 items: ItemA and ItemB.
Each item can be considered as one section.
FragmenA->FragmentA2->FragmentA3
FragmentB->FragmentB2->FragmentB3
But in my situation, when I click on back button on Fragment B2, somehow app goes back to Fragment A2(which previously was opened)
Even on Fragment B3, back button causes to go to Fragment A2.
How to solve these problems?
Related
I have an activity with a viewpager that contains 2 tabs. Each tab is a host fragment that has 2 child fragments. First fragments are recyclerviews that open up other fragments with FragmentTransactions. I am having trouble creating different backstacks for them.
So in my recyclerview adapter in onBindViewHolder i have the onclicklistener like this:
holder.image.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
FirstFragment fragment1 = new FirstFragment();
SecondFragment fragment2 = new SecondFragment();
FragmentManager fm = ((FragmentActivity) view.getContext()).getSupportFragmentManager();
FragmentTransaction transaction = fm.beginTransaction();
transaction
.replace(R.id.frame_container, fragment2,"Tag")
.addToBackStack(null)
.commit();
}
});
If i make the transaction like this from the recyclerview, the backstack is the same for both tabs, so if i open second fragments on tab1, then on tab2, if i go back to tab1 and press back, the second fragment on tab2 gets popped insead.
If i make a button in the FirstFragment outside of the recyclerview and make the fragment transaction from FirstFragment like this:
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
final FragmentTransaction ft = getFragmentManager().beginTransaction();
ft.replace(R.id.frame_container, SecondFragment.newInstance(), "Tag");
ft.addToBackStack(null);
ft.commit();
}
});
then it works as intended, but i want to do it from the recyclerview.
Is there any way this can be done?
You should carry your item click listener logic into the host fragment of the tab. Then in both of your host fragments you should make required transaction by using child fragment manager. Thus, the transactions are kept in the back stack of the host fragments. Then you have to manage these different stacks which are activity's fragment stack, host1's fragment stack and host2's fragment stack. For that purpose, you have to override onBackPressed in your activity then you ask the current visible host fragment for if there is a transaction. If there is you should pop that transaction and return in onBackPressed callback.If there is no let the activity to handle event by calling super.
I use one activity multiple fragments in my app. I use a shared element animation. I have two fragments, one of them is a detail page.
I don't want to addToBackStack function for fragment transition. And the detail fragment returns without animation for some cases. (fragmentMain->fragmentDetail)
DetailFragment detailFragment = new DetailFragment();
Transition moveTransition = TransitionInflater.from(MainActivity.singleInstance)
.inflateTransition(android.R.transition.move); // android.R.transition.move
moveTransition.setDuration(400);
detailFragment.setSharedElementEnterTransition(moveTransition);
FragmentManager fragmentManager = MainActivity.getActivityFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction()
.addSharedElement(sharedView, sharedView.getTransitionName())
.replace(R.id.mainLayout, detailFragment);
fragmentTransaction.commitAllowingStateLoss();
fragmentManager.executePendingTransactions();
This code works for me. I know that if I use addToBackStack, fragmentDetail->fragmentMain reveal animation works automatically. But I don't want to the use back stack.
Below code doesn't works for fragmentDetail->fragmentMain.
detailFragment.setSharedElementReturnTransition(moveTransition);
mainFragment.setSharedElementEnterTransition(moveTransition);
FragmentManager fragmentManager = MainActivity.getActivityFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction()
.addSharedElement(textView, textView.getTransitionName())
.replace(R.id.mainLayout, mainFragment);
fragmentTransaction.commitAllowingStateLoss();
fragmentManager.executePendingTransactions();
How can I do shared element animation for this case?
Look at your onCreateView function. If It recreate the layout, it breaks the transition id.
Solution:
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
if(inflatedView != null)
return inflatedView;
inflatedView = inflater.inflate(R.layout.fragment_blank, container,
return inflatedView;
}
This question already has answers here:
How to open a Fragment on button click from a fragment in Android
(3 answers)
Closed 6 years ago.
I tried the following code:
Intent in= new Intent(Activity1.this,Fragment.class);
startactivity(in);
This is not how fragments work, fragments must be attached to an Activity. To get your desired effect you must either start a new Activity that contains the fragment you wish to show, or display the new fragment in the current Activity.
In order to decide between which approach to take, I would consider how you want the Fragment to affect the navigation of your interface. If you want the user to be able to get back to the previous view by using the Back button, you should start a new Activity. Otherwise you should replace a view in your current Activity with the new Fragment.
Though, it is possible to add a Fragment to the back stack, I would only attempt to do so if you are confident with the structure of your user interface.
To show a new fragment in the current Activity you can use a FragmentTransaction:
Fragment fragment = CustomFragment.newInstance();
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
transaction.replace(R.id.container_layout, fragment).commit();
write this code in your onCreate or in your intent:
FragmentManager fm = getSupportFragmentManager();
YourFragment fragment = new YourFragment();
fm.beginTransaction().add(R.id.main_contenier,fragment).commit();
Fragments not Open through Intent.
You should use Fragment manager.
Fragment fragment= new YourFragment();
FragmentTransaction transaction = getFragmentManager().beginTransaction();
transaction.replace(R.id.fragment_container, fragment); // fragment container id in first parameter is the container(Main layout id) of Activity
transaction.addToBackStack(null); // this will manage backstack
transaction.commit();
Sample Example of Fragment
public class MyFragment extends Fragment implements View.OnClickListener {
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view= inflater.inflate(R.layout.fragment_my, container, false);
Button button1= (Button) view.findViewById(R.id.button1_Id);
Button button2= (Button) view.findViewById(R.id.button2_Id);
return view;
}
button1.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Fragment fragment= new YourFragment();
FragmentTransaction transaction = getFragmentManager().beginTransaction();
transaction.replace(R.id.fragment_container, fragment); // fragmen container id in first parameter is the container(Main layout id) of Activity
transaction.addToBackStack(null); // this will manage backstack
transaction.commit();
}
});
}
I have an Activity with a Layout named "container" where Fragments are inflated in using FragmentTransactions
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
transaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_CLOSE);
transaction.replace(R.id.container, SomeFragment.newInstance());
transaction.addToBackStack(null);
transaction.commit();
One Fragment inflates another fragment with two more Fragments in a TabLayout. This is done with a TabLayout and a ViewPager. Everything works well until I pop it from the backstack.
getSupportFragmentManager().popBackStack();
When I do this, the tabs are recreated and all the lifecycle methods are called. However, they have no content. They layouts seem not to be inflated.
I have a method called initUI(View v) which is called in
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_tabs, container, false);
initUI(rootView);
return rootView;
}
It does the setup for the TabLayout.
private void initUI(View rootView) {
pager = (ViewPager) rootView.findViewById(R.id.viewPagerCollected);
tabLayout = (TabLayout) getActivity().findViewById(R.id.tabs);
pager.setAdapter(new MyPagerAdapter(getActivity().getSupportFragmentManager()));
tabLayout.setupWithViewPager(pager);
tabLayout.setVisibility(View.VISIBLE);
}
Again, this method is called but doesn't seem to do anything when popping the backstack.
What am I doing wrong here? Why is the Fragment not recreated properly even though the onCreateView and initUI are being called?
EDIT: In my TabsFragment, each Fragment has a RecyclerView. When clicking one of the Items, another Fragment opens up, displaying detailed information to the user.
Here the user can navigate back. When doing this, the TabsFragment is visible again but this time without any content. It seems like the inner fragments have not being inflated this time around.
First Add to back stack like this...
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
transaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_CLOSE);
transaction.replace(R.id.container, SomeFragment.newInstance());
transaction.addToBackStack("YOUR_TAG");
transaction.commit();
After than try to popstackback()
In my app i have one activity and multiple fragments,From Activity A onCreate() i just show my HomeFragment and after user click events on my HomeFragment it moves to different fragment Like AboutFragment,Galleryfragment etc.
My problem is that when user move like ->HomeFragment -> AboutFragment ->GalleryFragment amd hen press virtual back button then view of GalleryFragment and AboutFragment overlaps each other.
I am using following code when move between fragment-
FragmentTransaction ft = fragmentManager.beginTransaction();
Fragment mFragment = new AboutFragment();
ft.replace(R.id.content_frame, mFragment);
ft.addToBackStack(null);
ft.commit();
So how can i solve this issue.
and i saw following eror in logcate-
FATAL EXCEPTION: main
java.lang.IllegalStateException: Fragment already added: AboutFragment{41c8a878 #0 id=0x7f07003d}
at android.support.v4.app.FragmentManagerImpl.addFragment(FragmentManager.java:1175)
at android.support.v4.app.BackStackRecord.popFromBackStack(BackStackRecord.java:722)
at android.support.v4.app.FragmentManagerImpl.popBackStackState(FragmentManager.java:1516)
EDIT:
my onCreateView of AboutFragment is-
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.aboutview, container,false);
aboutView = (TextView) view.findViewById(R.id.about_textview);
return view;
}
thanks in advance.