I have a dialog extended class. I want to call a fragment to be displayed on a click of a button. I am using this method:
public void onClick(View v) {
dismiss();
SearchingFragment mySearchengine = new SearchingFragment();
FragmentManager fragmentManager = getFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.replace(R.id.content_frame, mySearchengine);
fragmentTransaction.addToBackStack(null);
fragmentTransaction.commit();
}
// Perform button logic
});
But, my application crashes.
what I want my application to do is to dismiss the dialog and then call the fragment.
What you should do is to pass back the button event of your dialog fragment to the host activity, check the Passing Events Back to the Dialog's Host chapter in the Android dialog documentation. This is not only a good practice, but saves you alot of trouble, when you want to reuse the dialog.
Related
I'm creating a fragment which is supposed to act like a menu. I have successfully inflated it to the activity where I wanted it to be, however I now I realise that I cannot close the fragment. Furthermore I am able to scroll the contents of the activity which the fragment is placed over. How can I edit my code in such a way that the fragment will close after an action on the activity is detected, or one of it's contents is clicked?
I created the fragment by simply adding a fragment via new -> Fragment -> Fragment(Blank). I have not touched any of the code and have initialized the fragment like so in a on click:
findViewById(R.id.Menu).setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.setCustomAnimations(R.anim.enter_from_left, R.anim.exit_to_left, R.anim.enter_from_left, R.anim.exit_to_left);
MenuFragment menuFragment = new MenuFragment();
fragmentTransaction.replace(android.R.id.content, menuFragment);
fragmentTransaction.commit();
}
});
This is what it looks like, ignore the horrendous design.
I am trying to do the following use case in Android Fragments. I have 2 fragments.
Fragment A -> Fragment B
When a user does something in Fragment B, I want to have the back stack as follows
Fragment A -> Fragment C. So, when the user presses back I want the user to go back to Fragment A.
I have tried the following
mFragmentManager.popBackStackImmediate();
FragmentTransaction fragmentTransaction = fMgr.beginTransaction()
.replace(R.id.base, Fragment_C, "1")
.addToBackStack(null)
.commitAllowingStateLoss();
The problem here is that I can see Fragment A for a short period of time before Fragment C is shown
If I do the following
mFragmentManager.popBackStackImmediate();
FragmentTransaction fragmentTransaction = fMgr.beginTransaction()
.replace(R.id.base, Fragment_C, "1")
.addToBackStack(null)
.commitNowAllowingStateLoss();
I get the error
This transaction is already being added to the back stack
I can get Fragment C to show up if I do this BUT
mFragmentManager.popBackStackImmediate();
FragmentTransaction fragmentTransaction = fMgr.beginTransaction()
.replace(R.id.base, Fragment_C, "1")
.commitNowAllowingStateLoss();
This works and I don't see Fragment A and see Fragment C but the back button takes the user out of the application. So, is it possible that we can pop the back stack of the fragment and then add another fragment to the back stack w/o showing Fragment A AND the back button takes the user back to Fragment A
Here is an easy method to add fragments to fragments or to adapters within fragments...
from your base activity, make your fragment manager static. assume this activity is called dashboard.
static FragmentManager support;
Don't forget to initialize this in onCreate.
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.layout_dashboard);
support = getSupportFragmentManager();
define your new fragment inside your adapter or fragment.
users_item_fragment dialog = new users_item_fragment();
//also, let's add some data...
Bundle args = new Bundle();
args.putString("device", devicesList.get(position));
use the following method to add the fragment easily wherever you would like
//pick an easily remembered tag
public void replace(Fragment fragment, String tag){
FragmentManager man = dashboard.support;
FragmentTransaction fragt = man.beginTransaction();
if(!fragment.isAdded()) {
dashboard.lastTag = dashboard.fragtag;//not needed, but helpful w/ backpresses
fragt.add(R.id.fragment_container, fragment, tag)
.hide(man.findFragmentByTag(fragtag)).commit();
dashboard.fragtag = dashboard.tag;//not needed, but helpful w/ backpresses
}
if(fragment.isAdded() && fragment.isHidden()) {
dashboard.lastTag = dashboard.fragtag;//not needed, but helpful w/ backpresses
fragt.show(fragment);
fragt.hide(man.findFragmentByTag(fragtag)).commit();
dashboard.fragtag = dashboard.tag;//not needed, but helpful w/ backpresses
}
}
To implement this with backpresses working correctly, add this in you onBackPress method of your main activity:
#Override
public void onBackPressed() {
FragmentManager man = getSupportFragmentManager();
FragmentTransaction fragmentTransaction = man.beginTransaction();
fragmentTransaction.hide(getSupportFragmentManager().findFragmentByTag(fragtag))
.show(getSupportFragmentManager().findFragmentByTag(lastTag)).commit();
fragtag = lastTag;// holds the last fragment
}
}
It's easy to see the logic here and easy to manipulate back press events using this.
i have a parent fragment and when i click in a button to open first fragment then click in button in first fragment to open a second fragment and from second fragment to third fragment and so on ....
i succeeded to do that but the application becomes very slow after launching multiple fragments
this is the code i used to launch any fragment
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view)
{
Fragment newFragment = new newFragment();
FragmentTransaction transaction =
getFragmentManager().beginTransaction();
transaction.replace(fragmentContainer.getId(), newFragment);
transaction.addToBackStack(null);
transaction.commit();
}
});
When you are calling android.support.v4.app.FragmentManager then you must use getSupportFragmentManager().
public FragmentManager getSupportFragmentManager ()
Return the FragmentManager for interacting with fragments associated
with this activity.
If your new fragments are not transparent, I think you should check the overdraw of layouts.
The replace() needs to recreate the instance and reload data, maybe add() and hide() can help you.
i should use getActivity().getSupportFragmentManager() instead of getFragmentManager()
I have used the following codes for showing and canceling dialogfragment :
public static void showDialogFragment(FragmentManager fm,String type){
FragmentTransaction ft = fm.beginTransaction();
MyDialogFragment prev = (MyDialogFragment)fm.findFragmentByTag(type);
if (prev != null) {
prev.dismissAllowingStateLoss();
ft.remove(prev);
}
ft.addToBackStack(null);
MyDialogFragment newFragment = MyDialogFragment.newInstance();
try{
newFragment.show(ft,type);
}catch(IllegalStateException e){
return;
}
}
public static void cancelDialogFragment(FragmentManager fm,String tag){
FragmentTransaction ft = fm.beginTransaction();
MyDialogFragment prev = (MyDialogFragment )fm.findFragmentByTag(tag);
if (prev != null) {
prev.dismiss();
ft.remove(prev);
}
ft.addToBackStack(null);
ft.commit();
}
when I open the activity I show a dialogFragment and after receiving the data from internet I cancel it and show the recieved data, But if I press back button again it shows the dialogFragment and I have to press back button again to dismiss it and one more time to finish the activity. I know I can override onBackPressed but I want to know why this happens? why dose it again show the dialogfragment?
What is wrong with my code?
What you do is in showDialogFragment() you add this fragment to FragmentManager to backstack. Then in cancelDialogFragment() method you remove it from backstack with ft.remove(prev);
So now, your backstack is as it was before showing DialogFragment.
But what you do next is, that you add this DialogFragment again to backstack. It is not shown, but it is on the top of backstack. That means, if you press backButton, the top item in backstack, your DialogFragment, will be shown. On the next BackPress, your DialogFragment will be dismissed.
So dont add the fragment to backstack in your cancelDialogFragment() method.
Remove this line:
ft.addToBackStack(null);
Replace your entire cancelDialogFragment with this:
public static void cancelDialogFragment(FragmentManager fm,String tag){
fm.popBackStack();
}
Finally I have found the reason and the correct answer. the problem is with:
ft.addToBackStack(null);
From document:
Add this transaction to the back stack. This means that the
transaction will be remembered after it is committed, and will reverse
its operation when later popped off the stack.
Parameters name An optional name for this back stack state, or null.
that menas:
hey android I have removed dialogfragment from backstack (so there is nothing on the top of the backStack and the answer of #Vojtaaa9 is wrong because as I added the comment when you run MyDialogFragment prev = (MyDialogFragment )fm.findFragmentByTag(tag); after calling cancel you will get null, this means the backStack dose not have any dialogfragment) but remmber my action, remember that there was a dialogfragment but now it has removed. When user presses the back button the transaction reverses, it means that now there is nothing on the top of the backStack but then android pushes a dialogFragment to the backStack to do the transaction in a reverse order.
I have an application that is using fragments. The set up is like so:
Main Activity loads, loads fragment activity into right portion of parent activity
-From the Fragment, I launch a DialogFragment which displays a list of users
-From the DialogFragment, if you click on one of the users in the list, it hides the list of users DialogFragment .hide() and shows a new DialogFragment containing the details about the user
This all works great. However, when I click the Close button on the Details DialogFragment, I'd like to dismiss() that dialog, and re-show the List of Users dialog.
I realize this is somewhat difficult to follow.
Does anyone have any insight that may help me?
UPDATE
The code I use to display the DialogFragment is the following:
MyDialogFragment dialog = new MyDialogFragment();
dialog.show(getFragmentManager(), "MyDialogFragment");
Then once in the dialog fragment, if I wanted to hide it and show the details fragment I call
dialog.hide();
MyDetailsFragment details = new MyDetailsFragment();
details.show(getFragmentManager(), "MyDetailsFragment");
Basically I need to be able to re-show the dialog above when I dismiss the details.
When a fragment transaction is performed, you can add it to the back stack which can be reversed on dismissing the dialog.
Begin a fragment transaction and use the DialogFragment.show(FragmentTransaction transaction, String tag) variant which takes the FragmentTransaction as parameter. It will take care of showing the Dialog, adding the fragment to the passed transaction and then committing the transaction. Later when the Dialog is dismissed, DialogFragment will itself take care of popping the transaction.
You can follow the first sample posted in the DialogFragment docs.
Here is the working code:
public void launchMyDialog(View v) {
// DialogFragment.show() will take care of adding the fragment
// in a transaction. We also want to remove any currently showing
// dialog, so make our own transaction and take care of that here.
FragmentTransaction ft = getFragmentManager().beginTransaction();
Fragment prev = getFragmentManager().findFragmentByTag("mydialog");
if (prev != null) {
ft.remove(prev);
}
ft.addToBackStack(null);
MyDialogFragment dialog = new MyDialogFragment();
dialog.show(ft, "mydialog");
}
public static class MyDialogFragment extends DialogFragment {
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.fragment_main, container, false);
Button b = (Button) v.findViewById(R.id.button);
b.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
FragmentTransaction ft = getFragmentManager().beginTransaction();
Fragment prev = getFragmentManager().findFragmentByTag("mydialog");
if (prev != null) {
ft.remove(prev);
}
ft.addToBackStack(null);
MyDetailsFragment dialog = new MyDetailsFragment();
dialog.show(ft, "mydialog");
}
});
return v;
}
}