Open fragment from inside of another fragment - android

as the questions say I am trying to open a fragment from within another fragment. I have a navigation bar that contains all of my current fragments. However, I would like to open up a separate fragment from within one of these, so that the user can do some stuff (navigate to the contact list fragment and add a new contact thus opening a new fragment to help the user create it). So far when I click my add button, nothing happens (it's supposed to display a new fragment). I have searched around StackOverflow and google, but I can't fix my problem. My onClick() looks like:
addbutton = view.findViewById(R.id.addAlarm);
addbutton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
addbutton.setText("hello");
//this is just a textView for simplicity
CreateAlarm fragment = new CreateAlarm();
FragmentManager manager = getFragmentManager();
FragmentTransaction transaction = manager.beginTransaction();
//transaction.replace(R.id.main_frame, new CreateAlarm());
transaction.add(R.id.main_frame, fragment);
transaction.addToBackStack(null);
transaction.commit();
}
}
My navigation bar uses main_frame to display my normal fragments. It makes sense to me that that's where I would try to add or replace my new fragment. I believe this could be something that has to do with using a navigation bar maybe since I've never had this problem before. My implementation seems spot on from what I have seen in explanations. Any tips would be amazing.

Ok, well turns out I was calling the same fragment xml file in my OnCreateView for CreateAlarm instead of the new one, thus why I was not seeing any change. Just took me an entire day, but I will leave this up as an example for other people since my code works (both the replace and add fragment calls work properly).

Related

Best Practice/usual way to switch between 2 fragments in FrameLayout

I working on a app whitch has 1 activity with 2 buttons (Map and Listview). By clicking on the buttons the fragment into the FrameLayout needs to change from a listview to a mapview (or from map to listview).
I got this working and the fragments are show the data exacly as i want BUT...
I have a few problems by switching between the fragments. I struggled with the code and the best i got working is this:
FragmentManager fragmentManager;
Fragment listOverview;
AlertOverviewMapsFragment mapsOverview;
#Bind(R.id.fr_overviewContainer) FrameLayout fr_overviewContainer;
#OnClick(R.id.btn_list_overview) void openListOverview()
{
// Add the fragment to the 'fragment_container' FrameLayout
if (listOverview == null) { listOverview = new AlertOverviewListFragment();}
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fr_overviewContainer.removeAllViews();
fragmentTransaction.add(R.id.fr_overviewContainer, listOverview).commit();
}
#OnClick(R.id.btn_maps_overview) void openMapsOverview()
{
// Add the fragment to the 'fragment_container' FrameLayout
if (mapsOverview == null){ mapsOverview = new AlertOverviewMapsFragment();}
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fr_overviewContainer.removeAllViews();
fragmentTransaction.add(R.id.fr_overviewContainer, mapsOverview).commit();
}
The problem is when i click a second time on a button the app crashes and i get a java.lang.IllegalStateException: Fragment already added error. I understand that it means that i added the fragment to the manager (or transaction, dunno). I can create or find some workarounds for this but since this is nothing new i'am looking for the usual way to switch (replace) between the 2 fragments.
The fragments contains data which are loaded from the internet, it will be nice when the data is saved and loaded again by reloading the fragment. (so the user sees the old data when it is updated again in the background)
A CLEAR code example would be nice.....
i read something about the fragment manager and transactions and so as i understand the manager makes it posible to add, remove, delete......... fragments from a transaction? so i need 1 transaction per activity? or is this twisted? so the manager contains the fragments? this part is not clear and realy complicated for me. I'am happy when someone can help me with a solution for my problem and it would be nice when someone can explain how the transactions and the managers work in a realy SIMPLE way becouse i'am just started with programming Android apps.
Thanks for reading my problem and lot more thanks for the people who takes the time and patience for writing an answer!

Android fragments and creating new instances of them. Do you always need a container?

Fragments is something that I am still trying to understand, I get some of it but not all of it.
My question is, do i need a container to start a new fragment instance?
This is what I have been currently doing to launch a fragment from my current activity that i have a container in.
FragmentManager fm = getActivity().getFragmentManager();
FragmentTransaction ft = fm.beginTransaction();
ft.replace(container.getId(), new OtherFragment());
ft.commit();
So my main activity has a container where I can switch from 4 fragments. Now lets say I click on one of the list items in my 3rd tab. That launches a new activity that shows another listview. Then if i click on the item on that listview, i launch a new activity. Then, were it says "tap for more information", I will be launching a new activity (I haven't created this yet, and that is why I am asking this).
But I feel like it could just be launching fragments instead of activities. If so, how do I go about doing that, because I feel like I need some type of container to put it in since I have tried launching a newinstance of a dummy fragment class i created it but it doesn't launch. If not, how do i just create a new instance of it without a container, if possible.
Or do I only use fragments whenever they will be similar and will have a container to be put in??
And I could do fragmentActivity, but that is almost the same as Activity. The reason I ask is because we shouldn't have so many activities, right? or does having as many as activities as you want not affect the project performance? Because right now I usually create activities for everything, unless its like the first picture where I will have something similar that can be put into a container.
Thanks.
You're going to to pretty much the same thing that you did to show the first fragment.
FragmentManager fm = getActivity().getFragmentManager();
if (mDetailFragment == null)
{
mDetailFragment = new DetailFragment();
}
FragmentTransaction ft = fm.beginTransaction();
ft.replace(container.getId(), mDetailFragment);
ft.commit();
You're going to want to keep references to your fragments so you're not creating them new every time. To improve the user experience you can add animations to the transition and, if it makes sense, add the fragment to the backstack.
ft.addToBackstack("OtherFragment");
ft.setCustomAnimations(R.anim.enter, R.anim.exit, R.anim.popEnter, R.anim.popExit);

Replaced fragment still visible

When I start my app it runs an AsyncTask to load up and then in onPostExecute, I then setContentView to the new layout then add a fragment with two buttons offering two modes by an add FragmentTransaction. After one of the two modes is clicked, it then replaces the fragment with yet another FragmentTransaction using the replace method.
If the app crashes it returns to the first screen, loading up the two buttons offering the two modes. In this case if either mode is selected, the second fragment is loaded but is now the background is suddenly transparent showing the two buttons below and they remain clickable. If they are clicked again they properly replace the fragment so that it isn't visible below. This is just weird, I can't understand what could cause this.
I've researched and seen these two similar questions, one and two, which suggested that it might be because the ID is wrong or I have defined the fragment in XML. Neither of these two factors are the case.
My code is shown below:
Below I replace the loading screen.
#Override
protected void onPostExecute(Void result) {
setContentView(R.layout.activity_main_screen);
FragmentTransaction transaction = getSupportFragmentManager()
.beginTransaction();
transaction.add(R.id.fragment_container, new ModeFragment())
.commit();
}
After which, when a button is clicked I pass the fragment I wish to replace the current with into this method below:
private void replaceCurrentFragment(Fragment fragment) {
FragmentTransaction transaction = getSupportFragmentManager()
.beginTransaction();
transaction.replace(R.id.fragment_container, fragment)
.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN)
.addToBackStack(null).commit();
}
This works the first time, however if a crash occurs then the app returns to the first fragment and the second time this method is passed, the new replacing fragment is semi-invisible. Clicking the button on the first fragment again calls this method again and it is now fine.
Obviously I don't want the app to crash so this shouldn't occur, but I get this feeling that there's something wrong with how I'm writing my code.
I've had the same problem happen to me, and it was because I loaded a fragment in the OnCreate of my Activity, without checking if there was a savedInstanceState, so android first reopen all old fragments, then do the OnCreate, which added the fragment over the old ones without replacing them so when you navigate to another fragment, it only replaces the top one, but not the bottom one, so you will see the fragments under it.
Might not be exactly the same thing for you, but it might help you figure it out.

Transaction of fragments in android results in blank screen

If it helps, what I want is similar to what is done in this google tutorial
But there a fragment is created prior to the transition. If I do that the transition works fine; but I can't use this approach
=====
Aiming to API 7+ I am just trying to have one Fragment visible in the whole screen and using a button (a drawn button, with an onTouch event) then alternate to a second fragment and viceversa.
But I either get a blank screen when I replace the first fragment with the second, or if I use fragmentTransaction.show and fragmentTransaction.hide; I can switch two times before I get blank screen. I dont want to have on backstack.
I am creating the fragments in MainActivity's onCreate:
DiceTable diceTable = new DiceTable();
Logger logger = new Logger();
fragmentTransaction.add(diceTable, DICETABLE_TAG);
fragmentTransaction.add(logger, LOGGER_TAG);
fragmentTransaction.add(R.id.fragment_container, logger);
fragmentTransaction.add(R.id.fragment_container, diceTable);
Then on one method (called from the fragments) I do the switch:
Logger logger = (Logger)fragmentManager.findFragmentByTag(LOGGER_TAG);
DiceTable diceTable = (DiceTable)fragmentManager.findFragmentByTag(DICETABLE_TAG);
if (diceTable.isVisible()) {
fragmentTransaction.replace(R.id.fragment_container, logger);
fragmentTransaction.commit();
fragmentTransaction.hide(diceTable);
fragmentTransaction.show(logger);
}
else if (logger.isVisible()) {
fragmentTransaction.replace(R.id.fragment_container, diceTable);
fragmentTransaction.commit();
fragmentTransaction.hide(logger);
fragmentTransaction.show(diceTable);
}
This is not how I should do this?
Blank screen when replacing fragments
Try to initialize fragments in that way:
private void initFragments() {
mDiceTable = new DiceTable();
mLogger = new Logger();
isDiceTableVisible = true;
FragmentManager fm = getSupportFragmentManager();
FragmentTransaction ft = fm.beginTransaction();
ft.add(R.id.fragment_container, mDiceTable);
ft.add(R.id.fragment_container, mLogger);
ft.hide(mLogger);
ft.commit();
}
And then flip between them in that way:
private void flipFragments() {
FragmentManager fm = getSupportFragmentManager();
FragmentTransaction ft = fm.beginTransaction();
if (isDiceTableVisible) {
ft.hide(mDiceTable);
ft.show(mLogger);
} else {
ft.hide(mLogger);
ft.show(mDiceTable);
}
ft.commit();
isDiceTableVisible = !isDiceTableVisible;
}
You are combining two different methods of changing which Fragment is shown:
Calling replace() to replace the contents of the container with a different Fragment
Calling hide() to remove a Fragment, then calling show() to show another Fragment.
Pick one method and stick with it. The Building a Flexible UI guide uses just the replace() method, so I would start by trying to remove all of your calls to show() and hide().
Also see Android Fragments: When to use hide/show or add/remove/replace? for a quick summary of when it might be beneficial to use hide/show instead of replace.
In case anyone has tried all of the already suggested answers and is still facing the issue, like I was a few moments ago, the problem may come from a different source than your fragments.
In my case, I was switching between fragments correctly, but the reason for the blank screen was that in each new fragment I was trying to asynchronously load images by starting a new Thread every time (something a bit like this) instead of the recommended AsyncTask, or better yet the newSingleThreadExecutor, since AsyncTask is deprecated.
I disturbed the background enough that the fragment was just not showing up unless I navigated to a different app then back.
So unless your mistake is similar to mine my suggestion might be kind of vague but try to see if anything is happening in your fragment that may be intensive on the resources (commenting out different pieces of code may help in investigating this).

Swap two fragment simultaneously

In my application i have one activity and i am adding two fragments at run time.I need to swap these two fragment simultaneously. Fragment 1 consist a button and i want when i click that button fragment 1 moves to right side of the screen and other fragment to the left side of the activity.
In the onClick method of the button i tried something like this
#Override
public void onClick(View v) {
FragmentTransaction ft = getFragmentManager().beginTransaction();
Fragment newFragment = getFragmentManager().findFragmentById(R.id.pageA);
ft.remove(newFragment);
Fragment newFragmentB = getFragmentManager().findFragmentById(R.id.pageB);
ft.remove(newFragmentB);
ft.add(R.id.pageB, newFragment);
ft.add(R.id.pageA, newFragmentB);
ft.addToBackStack(null);
ft.commit();
}
But i am getting the following error
java.lang.IllegalStateException: Can't change container ID of fragment PageA{40653da0 #0 id=0x7f060001}: was 2131099649 now 2131099650
I want something like this when i click the button on Page A then Position of Page A and PageB should swap with each other.
I have a similar issue ( IllegalStateException: Can't change container ID of Fragment ) and i solved by swapping the containers instead of the fragments... Nonetheless i still have no clue as to whether it's possibile to swap directly fragments. As I wrote in the aforementioned post, it seems to work only on ics!
I posted a solution to this problem to a similar question. My approach is to re-create the fragment, but keeping the state by saving it first and re-applying it to the new instance.
See https://stackoverflow.com/a/14951987/599614.

Categories

Resources