My ERROR :
java.lang.IllegalStateException: commit already called
My CODE:
final FragmentTransaction fragmentTransaction =getFragmentManager().beginTransaction();
f1_fragment = new F1_Fragments();
f2_fragment = new F2_Fragments();
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
parent.getItemAtPosition(position);
if(position==0){
fragmentTransaction.replace(android.R.id.content, f1_fragment);
}else{
fragmentTransaction.replace(android.R.id.content, f2_fragment);
}
fragmentTransaction.addToBackStack(null);
fragmentTransaction.commit();
}
});
You are beginning the FragmentTransaction outside of the OnItemClickListener. Thus you are attempting to commit() a single FragmentTransaction every time the user clicks an item in your ListView.
You need to begin a new FragmentTransaction every time you intend to perform any number of Fragment operations.
A simple fix would look like this:
f1_fragment = new F1_Fragments();
f2_fragment = new F2_Fragments();
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
FragmentTransaction fragmentTransaction =getFragmentManager().beginTransaction();
parent.getItemAtPosition(position);
if(position==0){
fragmentTransaction.replace(android.R.id.content, f1_fragment);
}else{
fragmentTransaction.replace(android.R.id.content, f2_fragment);
}
fragmentTransaction.addToBackStack(null);
fragmentTransaction.commit();
}
});
you can use this method for replace fragment with each other just call this
do those are global
YourFragment1 frg1 = new YourFragment1 ();
YourFragment2 frg1 = new YourFragment2 ();
And then call it by
openFragment(frg1);
or
openFragment(frg2);
OpenFragment:
private void openFragment(final Fragment fragment) {
FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction transaction = fragmentManager.beginTransaction();
transaction.replace(R.id.container, fragment);
transaction.addToBackStack(null);
transaction.commit();
}
Look at this scenario
I need to add new fragment on every list item click. Just initialise fragment transaction on every item click.
switch (v.getId()) {
case R.id.tvaddExpense:
fragmentTransaction = getFragmentManager().beginTransaction();
fragmentTransaction.add(R.id.containerFucntionsList, new Fragment1());
fragmentTransaction.addToBackStack(null);
fragmentTransaction.commit();
break;
case R.id.relEvents:
fragmentTransaction = getFragmentManager().beginTransaction();
fragmentTransaction.replace(R.id.containerFucntionsList, new Fragment2());
fragmentTransaction.addToBackStack(null);
fragmentTransaction.commit();
break;
}
I had same issue and I have solved by creating new instance of FragmentTransaction.
Just add everytime below line before add / replace fragment.
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
Hope this would help you.
The Error
java.lang.IllegalStateException: commit already called
shows that the FragmentTransaction has been completed after calling commit() the first time and you are again calling commit() which tends to complete it once again. Hence it makes an Illegal state for the FragmentTransaction.
As per your code, you are using the same FragmentTransaction for changing fragments. However, after the first commit() call, the FragmentTransaction has completed and you need to begin it again to perform any operation on Fragments.
You can change your ClickListner as:
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
fragmentTransaction = getSupportFragmentManager().beginTransaction();
parent.getItemAtPosition(position);
if(position==0){
fragmentTransaction.replace(android.R.id.content, f1_fragment);
}else{
fragmentTransaction.replace(android.R.id.content, f2_fragment);
}
fragmentTransaction.addToBackStack(null);
fragmentTransaction.commit();
}
});
I hope it clears your doubt.
You must define a FragmentTransAction object separately each time you add a fragment:
switch (position){
case 0:
FragmentTransaction fragmentTransaction1 = getSupportFragmentManager().beginTransaction();
fragmentTransaction1.replace(R.id.parentOfMenu, new FragmentHome());
fragmentTransaction1.commit();
break;
case 1:
FragmentTransaction fragmentTransaction2 = getSupportFragmentManager().beginTransaction();
fragmentTransaction2.replace(R.id.parentOfMenu, new FragmentMedia());
fragmentTransaction2.commit();
break;
case 2:
FragmentTransaction fragmentTransaction3 = getSupportFragmentManager().beginTransaction();
fragmentTransaction3.replace(R.id.parentOfMenu, new FragmentChart());
fragmentTransaction3.commit();
break;
case 3:
FragmentTransaction fragmentTransaction4 = getSupportFragmentManager().beginTransaction();
fragmentTransaction4.replace(R.id.parentOfMenu, new FragmentProfile());
fragmentTransaction4.commit();
break;
}
I solved the issue
after calling commit() and again replacing the fragment you should start from
fragmentTransaction = fragmentManager.beginTransaction();
if(position==0){
fragmentTransaction.replace(android.R.id.content, f1_fragment);
else{
fragmentTransaction.replace(android.R.id.content, f2_fragment);
}
fragmentTransaction.addToBackStack(null);
fragmentTransaction.commit();
Related
I have a Android app with one activity and two fragments. First fragment (MainFragment) show a list of "items" and second (DetailsFragment) display a item's details (very basic).
On the normal flow, the activity start and show first fragment and the second is shown when a item is clicked.
But the second fragment can be shown directly throught click on a notification (by putting extra arguments to the activity).
String id = getIntent().getStringExtra("id");
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
if (id != null) {
fragment = new DetailsFragment();
Bundle args = new Bundle();
args.putString("id", id);
fragment.setArguments(args);
} else {
fragment = new MainFragment();
}
ft.replace(R.id.main, fragment);
ft.commit();
In the second case, the problem is : How to open MainFragment when clicking back from DetailsFragment ? Actually the app finish because only the second fragment has been created.
First way: Its very simple. You just need to use addToBackStack(null). It will save your desired fragment and when you use backpressed it will open that one.
Do something like this:
if (id != null) {
fragment = new DetailsFragment();
Bundle args = new Bundle();
args.putString("id", id);
fragment.setArguments(args);
ft.replace(R.id.main, fragment);
ft.commit();
} else {
fragment = new MainFragment();
ft.replace(R.id.main, fragment).addToBackStack(null);
ft.commit();
}
Second way: in your DetailsFragment's onResume() method write this code.
#Override
public void onResume() {
super.onResume();
getView().setFocusableInTouchMode(true);
getView().requestFocus();
getView().setOnKeyListener(new View.OnKeyListener() {
#Override
public boolean onKey(View v, int keyCode, KeyEvent event) {
if (event.getAction() == KeyEvent.ACTION_UP && keyCode == KeyEvent.KEYCODE_BACK) {
fragment = new MainFragment();
fragmentManager = getFragmentManager();
fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.replace(R.id.main, fragment);
fragmentTransaction.commit();
return true;
}
return false;
}
});
}
Add the main fragment in the onCreate() of the activity and override the onBackPressed() in the main activity
FragmentTransaction mFragmentTransaction = fragmentManager.beginTransaction();
mFragmentTransaction.replace(R.id.frame_container_recharege, fragment);
mFragmentTransaction.commit();
#Override
public void onBackPressed() {
FragmentManager fragmentManager = getSupportFragmentManager();
if (fragmentManager.getBackStackEntryCount() > 1) {
fragmentManager.popBackStack();
} else {
super.onBackPressed();
}
}
This is very common situation in Android, and simply saying you can just add it to backstack. So when user presses back button he will see the previous fragment(MainFragment).
getFragmentManager()
.beginTransaction()
.addToBackStack(yourFragment.getClass().getSimpleName())
.replace(R.example.container, yourFragment)
.commit();
Have a read official Android documentation about the back stack
UPDATE:
If you open DetailsFragment directly(without opening MainFragment) then you should check the back stack, if it is empty then open MainFragment manually. Here is the full code:
if (getSupportFragmentManager().getBackStackEntryCount() == 0) // empty back stack{
getFragmentManager()
.beginTransaction()
.replace(R.example.container, MainFragment)
.commit();
}
You can use something like this on your back press or back button clicked
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
fragment = new MainFragment();
ft.replace(R.id.fragment_container, frag);
ft.commit();
add fragment like this
FragmentManager manager = getSupportFragmentManager();
FragmentTransaction ft = manager.beginTransaction();
ft.replace(containerId, fragment);
ft.addToBackStack(backStateName);
ft.commit();
and in your activity backpress put this
getSupportFragmentManager().popBackStack();
I only know how to add fragment and remove.
also show and hide.
I just want to initialize fragment.
onCreate {
getFragmentManager().beginTransaction().add(R.id.top_container, new AuthProgressDialog(), AuthProgressDialog.class.getSimpleName()).commit();
getFragmentManager().beginTransaction().hide( getFragmentManager().findFragmentByTag(AuthProgressDialog.class.getSimpleName()) ).commit();
}
This is bad code, isn't it?
If you have any idea, please let me know.
Thanks.
This is sample method which you can define inside your FragmentActivity and call from any of the fragment. in which if you want to allowing adding to backstack than just remove comment line from transaction.addToBackStack("back"); and check popup backstack as per your requirement inside FragmentActivity.
public void displayView(int position) {
Fragment fragment = null;
switch (position) {
case 0:
fragment = new FormFragment();
break;
case 1:
fragment = new HomeFragment();
break;
}
if (fragment != null) {
FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction transaction = fragmentManager
.beginTransaction();
if (position != 0)
// transaction.addToBackStack("back");
transaction.replace(R.id.main_ll_container, fragment).commit();
} else {
Log.e("MainActivity", "Error in creating fragment");
}
}
Use this code :
FragmentManager fragmentManager = getFragmentManager()
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
Fragment fraggy = new DummyFragment();
fragmentTransaction.add(R.id.fragment_container, fraggy);
fragmentTransaction.commit();
I have a fragment activity from where i can start my fragments which contain a viewpager. In my fragment activity I have added this piece of code.
fragment = new ItemPagerFragment();
FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction transaction = fragmentManager.beginTransaction();
transaction.replace(R.id.content_frame, fragment);
transaction.addToBackStack(null);
transaction.commit();
Now when I press back button only blank screen appears and it does not lead me to my fragment activity.
What wrong i might be doing?
Use this in activity that holds fragment.
#Override
public void onBackPressed() {
if (fragmentManager.getBackStackEntryCount() > 1) {
fragmentManager.popBackStack();
} else
finish();
}
Try this way,
// Create new fragment and transaction
Fragment newFragment = new ItemPagerFragment();
// consider using Java coding conventions (upper first char class names!!!)
FragmentTransaction transaction = getFragmentManager().beginTransaction();
// Replace whatever is in the fragment_container view with this fragment,
// and add the transaction to the back stack
transaction.replace(R.id.content_frame, newFragment);
transaction.addToBackStack(null);
// Commit the transaction
transaction.commit();
Modify your code
#Override
public void onBackPressed() {
if(some condition) {
// do something
} else {
super.onBackPressed();
}
}
Please follow this link
Handling back button press Inside Fragments
You have to tell to the fragment manager that the back button was pressed. Override onBackPressed on your Activity
#Override
public void onBackPressed() {
if (getFragmentManager().getBackStackEntryCount() == 0) {
super.onBackPressed();
} else {
getFragmentManager().popBackStack();
}
}
private void changeFragment (Fragment fragment){
String backStackName = fragment.getClass().getName();
FragmentManager manager = getSupportFragmentManager();
boolean fragmentPopped = manager.popBackStackImmediate (backStackName, 0);
if (!fragmentPopped){ //fragment not in back stack, create it.
FragmentTransaction ft = manager.beginTransaction();
ft.replace(R.id.content_frame, fragment);
ft.addToBackStack(backStackName );
ft.commit();
}
}
While launching fragment assign a TAG to each fragment.When you want to back press check the existence of an fragment using assigned TAG name and then do corresponding action.for example:
private final static String TAG_FRAGMENT = "TAG_FRAGMENT";
//when want to add fragment to view
private void showFragment() {
final Myfragment fragment = new MyFragment();
final FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
transaction.replace(R.id.fragment, fragment, TAG_FRAGMENT);
transaction.addToBackStack(null);
transaction.commit();
}
//in activity back pressed check the existence of fragment by TAG
#Override
public void onBackPressed() {
final Myfragment fragment = (Myfragment) getSupportFragmentManager().findFragmentByTag(TAG_FRAGMENT);
if (fragment.allowBackPressed()) { // and then you define a method allowBackPressed with the logic to allow back pressed or not
super.onBackPressed();
}
}
i have 2 fragments, when i replace the second fragment and press the back button at that time my first fragment shows blank,here is my code
Fragment fragment = new MovieDetails();
Bundle args = new Bundle();
args.putString("background", item.getBackg());
args.putString("thumb", item.getThumb());
args.putString("id", item.getCode());
fragment.setArguments(args);
String backStateName = fragment.getClass().getName();
boolean fragmentPopped = getActivity()
.getSupportFragmentManager().popBackStackImmediate(
backStateName, 0);
if (!fragmentPopped) { // fragment not in back stack, create it.
FragmentTransaction ft = getActivity()
.getSupportFragmentManager().beginTransaction();
ft.replace(R.id.content_frame, fragment);
ft.addToBackStack("TAG");
ft.commit();
}
getActivity().getSupportFragmentManager().beginTransaction()
.replace(R.id.content_frame, fragment).commit();
You can do this
private void showFragment() {
final Myfragment fragment = new MyFragment();
final FragmentTransaction transaction =
getSupportFragmentManager().beginTransaction();
transaction.replace(R.id.fragment, fragment, TAG_FRAGMENT);
transaction.addToBackStack(null);
transaction.commit();
}
#Override
public void onBackPressed() {
final Myfragment fragment = (Myfragment)getSupportFragmentManager().findFragmentByTag(TAG_FRAGMENT);
if (fragment.allowBackPressed()) {
super.onBackPressed();
}
This probably isn't your problem, but it was mine: I'd over-ridden onSaveInstanceState() and forgotten to call through to super. This resulted in a blank fragment after pressing 'back', almost certainly because super.onSaveInstanceState() is where the fragment stack gets saved.
I am new to android working first time on fragment.I am creating an app in which I want to add a fragment on frame layout.I am able to do this but now what I want is to remove the same fragment which i added by that same button click I tried but couldn't. here is my code.
public void onClick(View v) {
android.support.v4.app.FragmentManager fragmentManager = getSupportFragmentManager();
if(v.getId() == R.id.clickme){
if(getSupportFragmentManager().findFragmentById(R.layout.fragment_one) != null){
// getSupportFragmentManager().beginTransaction().remove(getSupportFragmentManager().findFragmentById(R.layout.fragment_one)).commit();
Fragment fragment = new FragmenOne();
fragmentManager.beginTransaction().remove(fragment).commit();
}else{
Fragment fragment = new FragmenOne();
// android.support.v4.app.FragmentManager fragmentManager = getSupportFragmentManager();
fragmentManager.beginTransaction()
.replace(R.id.my_frame, fragment)
.commit();
}
}
}
You need to do in this manner
Fragment f = fragmentManager.findFragmentById(R.id.my_frame);
if(f instanceof FragmenOne) {
FragmenOne oneFragment = (FragmenOne) f;
FragmentTransaction trans = manager.beginTransaction();
trans.remove(oneFragment);
trans.commit();
fragmentManager.popBackStack();
}else{
Fragment fragment = new FragmenOne();
fragmentManager.beginTransaction()
.replace(R.id.my_frame, fragment)
.commit();
}