I have an Activity with a container being a FrameLayout. I need to add a fragment to that container, but doing so throws an IllegalStateException, destroying my Activity.
This is my container in the activity layout:
<FrameLayout
android:id="#+id/seeMoreContainer"
android:layout_width="match_parent"
android:layout_height="match_parent">
</FrameLayout>
This is how I add the fragment to the activity
PlacesSeeMoreFragment placesSeeMoreFragment = new PlacesSeeMoreFragment();
Bundle bundle = new Bundle();
bundle.putInt(PlacesSeeMoreFragment.KEY, poiID);
placesSeeMoreFragment.setArguments(bundle);
getSupportFragmentManager().beginTransaction().add(R.id.seeMoreContainer,
placesSeeMoreFragment).commit();
And this is the logcat
java.lang.IllegalStateException: Activity has been destroyed
at android.support.v4.app.FragmentManagerImpl.enqueueAction(FragmentManager.java:1515)
at android.support.v4.app.BackStackRecord.commitInternal(BackStackRecord.java:634)
at android.support.v4.app.BackStackRecord.commit(BackStackRecord.java:613)
at net.ilb.Activities.PlacesActivity.openPlaceSeeMore(PlacesActivity.java:140)
What am I doing wrong here?
EDIT:
I add the fragment to the activity from a public method, which I call from onItemClickListener of a ListView
This is the whole method
public void openPlaceSeeMore(int poiID){
PlacesSeeMoreFragment placesSeeMoreFragment = new PlacesSeeMoreFragment();
Bundle bundle = new Bundle();
bundle.putInt(PlacesSeeMoreFragment.KEY, poiID);
placesSeeMoreFragment.setArguments(bundle);
getSupportFragmentManager().beginTransaction().add(R.id.seeMoreContainer, placesSeeMoreFragment).commit();
}
And this is how the method is called
mListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
PlacesActivity placesActivity = new PlacesActivity();
placesActivity.openPlaceSeeMore(poi.getId());
}
});
I guess you are calling this:
PlacesActivity placesActivity = new PlacesActivity();
This is a very wrong approach to call a method declared in activity.
Which is creating new instance of your activity every time you click something on the list. Plus if you want to capture list clicks you should use an interface and not use activity objects anywhere.
Hope this helps.
Use below code....
Fragment fragment = new PlacesSeeMoreFragment();
FragmentManager fm = getActivity().getSupportFragmentManager();
FragmentTransaction ft = fm.beginTransaction();
ft.replace(R.id.content_frame, fragment);
ft.commit();
Bundle bundle = new Bundle();
bundle.putInt(PlacesSeeMoreFragment.KEY, poiID);
fragment.setArguments(bundle);
Sometime I faced the same issue and this is what I did. Use commitAllowingStateLoss() instead of commit(). Try this one
getSupportFragmentManager().beginTransaction().add(R.id.seeMoreContainer, placesSeeMoreFragment).commitAllowingStateLoss();
try this ,
PlacesSeeMoreFragment placesSeeMoreFragment = new PlacesSeeMoreFragment();
Bundle bundle = new Bundle();
bundle.putInt(PlacesSeeMoreFragment.KEY, poiID);
placesSeeMoreFragment.setArguments(bundle);
FragmentManager manager = getSupportFragmentManager();
FragmentTransaction transaction=manager.beginTransaction();
transaction.add(R.id.seeMoreContainer, placesSeeMoreFragment );
transaction.commit();
Related
I am using recyclerview in my app. I want to start a fragment when click on image view. But i don't know how to. Also i want to put data when starting fragment. I know how to start the activity with below code. But how can i start fragment same way?
Edited Code
FragmentManager fm = getSupportFragmentManager();
FragmentTransaction ft = fm.beginTransaction();
ft.replace(R.id.layoutContent, frag);
ft.commit();
Fragments cannot be started, they must be added to a container.
Fragments aren't meant to function on their own, they need an enclosing Activity.
Having the following layout:
[...]
<FrameLayout android:id="#+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="?android:attr/detailsElementBackground" />
[...]
You place the fragment in it like such:
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
transaction.replace(R.id.container, newFragment);
transaction.commit();
You pass arguments to the fragment by using Bundle and creating the fragment as follows:
TestFragment newFragment = new TestFragment();
Bundle args = new Bundle();
args.putString("Hello world!");
newFragment.setArguments(args);
This has to be done before the transaction.
For further info refer to the official documentation
Note on edited code: you have to call the transaction from inside the Activity the FrameLayout is part of. Alternatively use a rather dirty workaround:
In Main:
public class Main extends Activity{
public static Main currentInstance;
public void onCreate(Bundle boomerang){
currentInstance = this;
}
}
In the Playlist activity then use Main.currentInstance.getSupportFragmentManager() etc.
But I wouldn't recommend it.
In order to start a fragment you need to make use of the fragment manager.
YourFragment yourFragmentInstance = YourFragment.newInstance("Hello", 12);
FragmentTransaction fragmentTransaction = getFragmentManager().beginTransaction();
//Fragment is hosted by an activity, and the activity must have a layout
//or a container for the fragment to be nested in, in this case it will be
//a FrameLayout with an id fragment_container
fragmentTransaction.replace(R.id.fragment_container, yourFragmentInstance);
fragmentTransaction.commit();
And you can pass in arguments to your fragment like this:
public class YourFragment extends Fragment {
public static YourFragment newInstance(String paramOne, int paramTwo) {
YourFragment fragment = new YourFragment();
Bundle b = new Bundle();
//set params/arguments for fragment
b.putString("param_one", paramOne);
b.putInt("param_two", paramTwo);
fragment.setArguments(b);
return fragment;
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//Get the params you passed in
Bundle bundle = getArguments();
String paramOne = bundle.getString("param_one");
String paramTwo = bundle.getInt("param_two");
}
}
Note: I've not tested this code.. This is just an idea :)
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();
}
});
}
Hi I have A RecycleView Adapter and A button. I want that button to start a Fragment. I can start an activity but not a fragment. I have tried this Onclick method for my Button
#Override
public void onClick(View v) {
Bundle bundle = new Bundle();
bundle.putParcelable("event", events.get(getLayoutPosition()));
Fragment fragment = new EditEventDetailFragment();
fragment.setArguments(bundle);
fragment.getFragmentManager().beginTransaction().replace(R.id.contentMainDrawer,fragment).commit();
}
But have error invoke null object (contentMainDrawer) is my Main activity content_layout.
Any help is much appreciate. The Fragment host recycle view is call from Mainactivity
Use below code for replace fragment
Fragment fragment = new EditEventDetailFragment();
FragmentManager fragmentManager = getActivity().getSupportFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.replace(R.id.contentMainDrawer, fragment, "tag").commit();
if you are using this code inside adapter than replace getActivity() to ((Activity) context).
Hi I have found 2 answer that help whoever needed. The answer is to use the Activity that host the calling fragment. Many thanks #Mohit Suthar
Bundle bundle = new Bundle();
bundle.putParcelable("event", events.get(getLayoutPosition()));
Fragment fragment = new EditEventDetailFragment();
fragment.setArguments(bundle);
FragmentManager fragmentManager = ((MainActivity) context).getSupportFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.replace(R.id.contentMainDrawer, fragment, "tag").commit();
I am using the SherlockFragments library for the sliding menu.I have list of items as menu when
I click on item fragment get opened as an activity but it is a fragment.Now I am new to fragments.i don't know how to move from one fragment to another fragment.As in activity, we have intent to move to another activity.but in fragment I don't how to move to another fragment.I have a button in fragmentA.when I click on this button it moves to fragment B.
By googling I came to know that it has different cycles but anyhow I get toast msg when I click button
here is following code
public class Fragment2 extends Fragment {
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.actionnetworklogin, container, false);
Button login = (Button)view.findViewById(R.id.login);
login.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
Toast.makeText(v.getContext().getApplicationContext(),"login clicked", 5000).show();
}
});
return view;
}
}
Can someone please tell me how can I move one fragment to another fragment?
Is there any other method that I can use activities instead of fragments?
I have written code for all activities and java files but I don't know that sliding menu has fragmented and now I have to write all the code fragments.
It's simple Only three line code...
Fragment fragment = new SalesFragment();
FragmentManager fragmentManager = getFragmentManager();
fragmentManager.beginTransaction().replace(R.id.frame_container, fragment).commit();
This is the code I use to switch fragments inside a view:
FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction();
fragmentTransaction.replace([viewId], fragment, tag);
fragmentTransaction.addToBackStack(tag);
fragmentTransaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
fragmentTransaction.commit();
You can try this also:-
public void ButtonClick(View view) {
Fragment mFragment = new YourNextFragment();
getSupportFragmentManager().beginTransaction()
.replace(R.id.content_frame, mFragment ).commit();
}
FragmentManager fragmentManager = getFragmentManager();
fragmentManager
.beginTransaction()
.replace(R.id.frame_container,
new TeacherFragment()).commit();
FragmentTransaction fragmenttransaction = getSupportFragmentManager().beginTransaction();
FirstFragment regcomplainfragment = new FirstFragment();
fragmenttransaction.replace(R.id.content_frame, regcomplainfragment).addToBackStack("tag");
fragmenttransaction.commit();
//Below is the example
//In first Fragment
Fragment fragment = new YourFragmentClassName();
FragmentManager fragmentManager = getActivity().getSupportFragmentManager(); android.support.v4.app.FragmentTransaction ft= fragmentManager.beginTransaction();
ft.replace(R.id.flContent, fragment);
Bundle args = new Bundle();
// Pass the values what you want to send to next fragment
args.putInt("Year", rYear);
args.putString("Month", rMonth);
args.putInt("Industry", rIndustry);
fragment.setArguments(args);
ft.commit();
//In Second Fragment
//In onCreateView Method get the values
int strYear= getArguments().getInt("Year");
String strMonth = getArguments().getString("Month");
strIndustry= getArguments().getInt("Industry");
//That's it very simple
I use a master/detail flow and in every fragment I have a viewpager containing some forms but the thing is when I click on some other links from the master list, the content of the viewpager is lost. How to save this content so everytime I click on the same choice I find my data.
My code :
#Override
public void onItemSelected(String id) {
if (mTwoPane) {
// In two-pane mode, show the detail view in this activity by
// adding or replacing the detail fragment using a
// fragment transaction.
if(id.contains("1"))
{
Bundle arguments = new Bundle();
ItemDetailFragment fragment = new ItemDetailFragment();
fragment.setRetainInstance(true);
fragment.setArguments(arguments);
getSupportFragmentManager().beginTransaction()
.replace(R.id.item_detail_container, fragment).commit();
}
else if(id.contains("2"))
{
Bundle arguments = new Bundle();
ItemDetailFragment2 fragment = new ItemDetailFragment2();
fragment.setRetainInstance(true);
fragment.setArguments(arguments);
getSupportFragmentManager().beginTransaction()
.replace(R.id.item_detail_container, fragment).commit();
}
} else {
// In single-pane mode, simply start the detail activity
// for the selected item ID.
Intent detailIntent = new Intent(this, ItemDetailActivity.class);
detailIntent.putExtra(ItemDetailFragment.ARG_ITEM_ID, id);
startActivity(detailIntent);
}
}
EDIT:
I tried to modify my code this way :
if (id.contains("1")) {
Fragment currFragment = fm.findFragmentByTag(lastTag);
ItemDetailFragment newFragment = (ItemDetailFragment) fm.findFragmentByTag("f"+1);
FragmentTransaction ft = fm.beginTransaction();
ft.hide(currFragment);
if(newFragment==null)
{lastTag="f"+1;
newFragment=new ItemDetailFragment();
ft
.replace(R.id.item_detail_container, newFragment);}
else {
ft.show(newFragment);
}
ft.commit();
}
But i got a NullPointerException at android.support.v4.app.BackStackRecord.run(BackStackrecord.java:656)
Try to call setRetainInstance(true) in your fragments onCreate()
As writed here, if you do not add the transaction to the back stack, then the fragment is destroyed when removed or replaced.
You can hide current fragment, instead replacing, then add new. Like that:
int currPage = 0;
public void goToPage(int num) {
FragmentManager fm = getSupportFragmentManager();
Fragment currFragment = fm.findFragmentByTag("f" + currPage);
Fragment newFragment = fm.findFragmentByTag("f" + num);
FragmentTransition ft = fm.beginTransaction();
ft.hide(currFragment);
if(newFragment == null) {
// First use. Create new instance for page.
newFragment = new MyFragment();
ft.add(R.id.item_detail_container, newFragment, "f" + num);
} else {
// Fragment for page already added. Just show it.
ft.show(newFragment);
}
ft.commit();
this.currPage = num;
}
And don't forget to specify tag for initial page fragment too.
You can implement the onPause() or onStop() methods of your fragments and save the data when that methods are called, which happens automatically when they are removed.
Or you could perhaps go with the savedInstanceState.
It's better to save in the arrayList. Onclick store the image id in the arrayList.