I have A Navigation Drawer with list of items , and on click on a list item opens
another list of events(with A custom list adapter)[1 st fragment].
And a click on any of any of that list item i want to open a fragment which displays its details[2 st fragment] .
So i want to transfer position of item click from 1st frag to 2 nd frag ,
i have static data in 2 nd frag , how do i transfer that position ?
I tried with interface ,
but with every time i do anything i get error in logcat as 1st fragment is not attached to Main activity .
And i have created layout(and referred them as fragment) and there is NO so no Id to get in mainactivity in 'getFragmentById' ? Thanks .
Pass data in constructor of fragment
FragmentManager fm = SliderActivity.this
.getSupportFragmentManager();
FragmentTransaction ft = fm.beginTransaction();
HomeFragment fragment = new HomeFragment(your_data);
ft.replace(R.id.content_fragment, fragment, getResources()
.getString(R.string.homeText));
ft.commit();
in HomeFragment set the value from constructor
HomeFragment(String value){
this.value=value;
}
You can use getActivity() from a fragment to find the FragmentActivity in which the fragment resides.
Then you can use FragmentActivity.findFragmentByTag() to find the other fragment in this Actvity. `
Related
Imagine i have main activity that has viewpager. I have 2 fragments called (F1 & F2) that will transaction into viewpager.
Again imagine in F1 fragment i want to set a button. When clicking on button, i want to transaction other fragment call SUBF1 but not into F1 fragment.
My question is here!!! Is it possible to replace SUBF1 with it's parent means F1?My idea is that i want to replace sub fragment with it's parent fragment that has been kept on fragment's container in main activity?
final FragmentTransaction ft = getFragmentManager().beginTransaction();
ft.replace(R.id.details, new NewFragmentToReplace(), "NewFragmentTag");
ft.commit();
You can save the instance of current fragment, when you are
navigating from one fragment to other. When user press the back
button, you can open the specific fragment with the help of tag.
#Override
public void onBackPressed() {
String currentTag = currentFragment.getTag();
if(currentTag.equals(res.getString(R.string.fragmentTagTest)))
{
currentFragment = AnotherFragment;
replaceFragment() // integrate replace current fragment with new one.
}
}
I am using navigation drawer and it is simple to use. I am not providing the complete code but providing you detail which could be easy for you to understand my problem. I am using fragments these are about 8 in numbers and I am replacing them with one an other. But here comes a problem
I am replacing them on click event of the navigation drawer. but there are two main problems
After replacement , I can see the previous fragment in the background. does replace method just call the new fragment over it ? if yes then what should I do to old fragment not be visible in the background of my new fragment.
When I click navigation drawer Item , it loads the specific fragment successfully. but keeping in that fragment when I click to that specific item again it loads this fragment again and again. For example if drawer item num 3 opens fragment MyBook , then by clicking item num three 2 or many times would open fragment that much time.
So please some one answer me how to cure my app for such kind of actions which I described above.
I tried like this. Its working fine me
FragmentManager frgmanager = getFragmentManager();
frgmanager.popBackStack(null, FragmentManager.POP_BACK_STACK_INCLUSIVE);
FragmentTransaction frgTransaction = frgmanager.beginTransaction();
if(subitem.equalsIgnoreCase("subitem")){
Frag1 frg1 =new Frag1(mCtx);
frgTransaction.replace(R.id.inflate_layout, frg1);
}else if(subitem1.equalsIgnoreCase("subitem1")){
Frag2 frg2 =new Frag2(mCtx);
frgTransaction.replace(R.id.inflate_layout, frg2);
}else{
Frag2 frg3 =new Frag3(mCtx);
frgTransaction.replace(R.id.inflate_layout, frg3);
}
frgTransaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE);
frgTransaction.commit();
you can use addtobackstack in fragmentstranstion object.like
FragmentManager manager = getFragmentManager();
FragmentTransaction transaction = manager.beginTransaction();
transaction.replace(R.id.bodyfragment, new AnotherFragment());
transaction.addtoBackStack(null).commit();
Use replace-method of FragmentTransaction instead of add (http://developer.android.com/guide/components/fragments.html#Transactions)
FragmentManager manager = getFragmentManager();
FragmentTransaction transaction = manager.beginTransaction();
transaction.replace(R.id.bodyfragment, new AnotherFragment());
transaction.commit();
To avoid re-instantiating the fragment, keep track of the current open fragment and only do a fragment transaction, if we next-to-be-opened fragment is a different one than the current.
This may achieved like the following:
class MyActivity ... {
private String currentFragment;
private void openNewFragment(Fragment fragment) {
String newFragment = fragment.getClass().getSimpleName();
if (newFragment.equals(currentFragment)){
// new fragment already shown
return;
}
// Fragment transaction etc here:
}
}
Note that this only compares fragments based in their class name. Sometimes this might not be unique, e.g. if there is a DetailFragment class which displays information about an entity. Which entities details to show may depend on intent arguments.
The above code however will then prevent opening DetailFragment for Entity=1 if currently details for Entity=2 are shown. For these scenarios the information about the fragment kept needs to be extended (e.g. storing a Reference or WeakReference to the fragment instance itself).
I have an architectural issue in my application . I have used one activity with navigation drawer and several fragments .Now ,
Suppose I have two fragments A and B . navigation structure is somewhat:
A
A1
A2
B
B1
B2
where A1,A2 are of type A fragment and B1,B2 are of type B fragment. The only difference between same type of fragments eg. A1,A2 is of data .
my first approach :
whenever user click on A1,A2,B1,B2 . I just create a new instance of that type and replace the fragment.
Fragment fragment =A.newInstance();
private void replaceFragment(Fragment fragment) {
FragmentManager fragmentManager = getSupportFragmentManager();
fragmentManager.beginTransaction()
.replace(R.id.content_frame, fragment).commit();
mDrawerLayout.closeDrawer(rlDrawer);
}
Note : I do not want to add them to back stack.
Later on I realize this approach is inefficient as every time it will crate a new instance on that fragment even if they are of same type . As I said before the difference is only in data .So, I move to next approach
Second Approach :
Now my activity has Data member (references) of Fragment A and B . Now I will check if it is null only then create a new instance else just change the data :
if (A == null) {
a = A.newInstance();
} else {
((A) a).changeData();
}
replaceFragment(a);
Problem with this approach is that when I switch from fragment A1 to B1 the A1 fragment get destroyed but its reference remain with activity . Now When i switch back from B1 to A1 it will not create a new instance as you can see in above code but at the same time onCreate() method gets called on Fragment A.
Should I remove the reference from activity as soon as onDestroy() is called on a Fragment ?
Does my second approach is correct ?
Is there any better approach for this?
Thanks in advance.
I would slightly modify your first approach.
Use string tags for your fragment.
When you are replacing a fragment use the replace method with three parameters, example:
fragmentManager.beginTransaction()
.replace(R.id.content_frame, fragment, TAG_A1).commit();
where TAG_A1 is a unique String tag.
You can use the method findFragmentByTag from the FragmentManager to check if the fragment was already created before you do a replace.
FragmentManager fragmentManager = getSupportFragmentManager();
Fragment fragmentA1 = fragmentManager.findFragmentByTag(TAG_A1);
if(fragment == null) {
fragment = A.newInstance();
}
fragmentManager.beginTransaction()
.replace(R.id.content_frame, fragment, TAG_A1).commit();
My question is not easy to describe, but I will do my best:
On my tablet-app I have one activity with a listFragment A on left side and a detailFragment B on right side. So when I click an item on the list, the detailFragment shows the proper details of the chosen (list) item.
Now when I click a button on my detailFragment B. the fragment gets swapped with a new Fragment from type infoFragment. The listFragment on left side stays as it is.
So now, when I click another item on the List, I want the infoFragment to vanish and get a detailFragment once again.
My problem is, that i need some kind of check if currently there is an infoFragment or a detailFragment displayed. So that I can either just refresh the detailFragment OR stop the infoFragment and build a new detailFragment.
idea:
if ( //detailFragment is active ) {
updateContent();
}
else {
FragmentManager.buildDetailFragment();
}
have been fiddling for hours now, any help is appreciated!!
How can i figure it out whether there is a detailFragment or listFragment displayed?
edit:
i change my detailFragment with the infoFragment here:
FragmentManager fm = getFragmentManager();
Fragment fragment = fm.findFragmentById(R.id.details_fragment);
fragment = new InfoFragment();
fm.beginTransaction()
.replace(R.id.details_fragment, fragment)
.commit();
When you add a Fragment to your fragment manager with a FragmentTransaction you can specify a key value. You can then findFragmentByTag which will determine if the Fragment with that key value has been added to the fragment manager.
So long as you are not using a ViewPager or some other structure where multple fragments are added at once, searching for whether your fragment manager contains a fragment by tag will let you know which is currently displayed. You can then use the results of that search to update the fragment since the result is a reference to the fragment itself.
This means you can pass data from the FragmentActivity to the fragment directly by calling any publicly accessable fragment methods. For example
Fragment displayedFragment = fragmentManager.findFragmentByTag(TAG);
if(displayedFragment != null){ //null if no fragment with tag value
displayedFragment.updateList() //public method within fragment
}
MyFragment myFragment = (MyFragment)getFragmentManager().findFragmentByTag("MY_FRAGMENT");
if (myFragment.isVisible()) {
// add your code here
}
From Here
FragmentManager fm = getFragmentManager();
Fragment fragment = fm.findFragmentById(R.id.content_id);
now we can get the fragment name by getClass
fragment.getClass().getSimpleName()
You can get class of fragment and check which one it exactly is by calling getClass().
I have the MainActivity, it contains ListFragment and framelayout, I am able to change the fragments on list on item click.
I have a problem to replace the existing Fragment1 with the new Fragment2, on button click of Fragment1, Fragment2 should replace the Fragment1, and should have the same ListFragment at left, and back buttons should be properly handled,this means when I am in Fragment2 and press back button it should show the same ListFragment and Fragment1.
You need to use .replace to switch the two fragments, you also need add add the original to the backstack so you can recall it, and you need to override the back key operation to function that way. It would look something like this (using code from one of my projects, using the support library):
To show your first fragment:
menu = new MenuFragment_Main(); // instantiate fragment
getSupportFragmentManager().beginTransaction().replace(R.id.pane, menu).commit(); // display fragment
To swap it for the new fragment and add it to the backstack:
ListFragment_ShopListItem shoplist = new ListFragment_ShopListItem(); // instantiate fragment
getSupportFragmentManager().beginTransaction().replace(R.id.pane, shoplist).addToBackStack(null).commit(); // replace original fragment with new fragment, add original to backstack
And to override the back key to go back to the previous fragment:
public void onBackPressed() {
FragmentManager fm = getActivity().getSupportFragmentManager();
fm.popBackStack();
return;
}