I have been using jfeinstein's SlidingMenu. I am currently trying to find if a certain fragment is visible to the user. I first tried:
if(mainfrag.isVisible()){
Log.d("Frag","Main is visible");
}else{
Log.d("Frag","Main is NOT visible");
}
Which always printed that the fragment was NOT visible. I then tried:
android.support.v4.app.FragmentManager fragmentManager = getActivity().getSupportFragmentManager();
Log.d("Frag","CurFrag: "+fragmentManager.findFragmentById(R.id.content_frame).toString());
MainFragment mf = new MainFragment();
if(fragmentManager.findFragmentById(R.id.content_frame) == mf){
Log.d("Frag","This is Main");
}else{
Log.d("Frag","This is NOT Main :(");
}
This prints
So I know that the findFragmentById will tell me the current fragment but I don't know how I can logically compare it so I can do things only if it is visible.
I have never dived into the details of SlidingMenu and couldn't tell you what's wrong in the first problem.
But in your second problem, you are comparing two different objects.
MainFragment mf = new MainFragment();
fragmentManager.findFragmentById(R.id.content_frame) == mf
Here you create a new MainFragment, and try to compare it with a old instance. It can never be true. When comparing Objects, the address are compared. It will only return true if they are the same objects.
If you just want to check the class of object, use the following code:
Fragment f = fragmentManager.findFragmentById(R.id.content_frame);
if(f instanceof MainFragment)
// code here.
Get the fragment by tag or by I'd
Get the fragment's view
Get window visibility on the view will provide visibility
Related
I've written a method, setLoading in my activity that is responsible for setting the "loading" status of my app. This method is responsible for instantiating a LoadingFragment, removing any existing instances of it (Using FragmentManager) and then depending on it's first parameter loading, adding it to one of two possible containers (Depending on the top parameter).
protected LoadingFragment loadingFragment;
public void setLoading(boolean loading, boolean top) {
FragmentManager fragmentManager = getFragmentManager();
// Create LoadingFragment instance if it has not already been created
if (loadingFragment == null || !(loadingFragment instanceof LoadingFragment)) {
loadingFragment = new LoadingFragment();
}
// Remove the fragment first if it is present
fragmentManager
.beginTransaction()
.remove(loadingFragment)
.commit();
// Only if loading is true should we display the fragment
if (loading) {
// Decide which container we're going to put the fragment in
int id = top ? R.id.topContainer : R.id.container;
// Place the fragment in the right position
fragmentManager
.beginTransaction()
.add(id, loadingFragment)
.commit();
}
}
public void setLoading(boolean loading) {
setLoading(loading, true);
}
I am triggering setLoading(true) from elsewhere in my activity and I have commented out it's corresponding setLoading(false) while testing.
What I want to happen is for my LoadingFragment to appear every time setLoading(true) is called. The first call shouldn't remove anything since it at that point it doesn't exist. All subsequent calls should remove the existing LoadingFragment and add it again.
What happens is that the first call to setLoading(true) does indeed create the LoadingFragment and put it in the correct container. However, subsequent calls to setLoading(true) remove the fragment, but it never seems to be re-added. I have checked to see that the fragment does indeed exist and is of type LoadingFragment at the point it is added and I have also checked to ensure that it's onCreateView method is being called.
Am I doing something wrong?
Edit
Using the answer given below by H Raval as a base I have now come up with the following:
public void setLoading(boolean loading, boolean top) {
FragmentManager fragmentManager = getFragmentManager();
Fragment currentLoadingFragment = fragmentManager.findFragmentById(R.id.loadingFragment);
if (currentLoadingFragment != null) {
fragmentManager
.beginTransaction()
.remove(currentLoadingFragment)
.commit();
}
if (loading) {
int id = top ? R.id.topContainer : R.id.container;
fragmentManager
.beginTransaction()
.add(id, new LoadingFragment())
.commit();
}
}
This seems to work as expected. It seems that the primary difference is that this code is creating a new LoadingFragment instance each time (When loading = true) whereas originally I was trying to use the same instance and just adding/removing it using the FragmentManager.
Out of interest, is there a reason I need to create a new instance after using remove? Is this the correct way to do it? Or should it still work when using the same instance? Additionally, if it's recommended to create a new instance each time, is there anything I should do in terms of clean-up, freeing up resources etc. (Perhaps there's a way of gracefully destroying the obsolete instances)?
well i have made some changes in your code and works perfect for me..let me know if you face any difficulty
public void loadFragment(boolean loading, boolean top){
FragmentManager fragmentManager = getSupportFragmentManager();
loadingFragment = new LoadingFragment();
// Only if loading is true should we display the fragment
if (loading) {
// Decide which container we're going to put the fragment in
int id = top ? R.id.topContainer : R.id.container;
if(top){
if(fragmentManager.findFragmentByTag("loadingFragment")!=null)
fragmentManager.beginTransaction().remove(fragmentManager.findFragmentByTag("loadingFragment")).commit();
fragmentManager
.beginTransaction()
.replace(R.id.topContainer, loadingFragment,"toploadingFragment")
.commit();
}else{
if(fragmentManager.findFragmentByTag("toploadingFragment")!=null)
fragmentManager.beginTransaction().remove(fragmentManager.findFragmentByTag("toploadingFragment")).commit();
fragmentManager
.beginTransaction()
.replace(R.id.container, loadingFragment,"loadingFragment")
.commit();
}
}
I have a class derived from FragmentPagerAdapter and user swiping works fine (4 tabs), but I would like to show a page/tab/fragment from code. For example, when user taps a textview, I would like to switch to a specific fragment.
I've tried the following without success:
public void onClockClick(View v)
{
FragmentManager fm = getFragmentManager();
if (fm != null) {
fm.beginTransaction()
.setCustomAnimations(android.R.animator.fade_in, android.R.animator.fade_out)
.show(mainFragment)
.commit();
}
}
Am I barking up the wrong tree?
Well, if you know the position of the fragment you want to show then you can simply do: pager.setCurrentItem(pos)
This will automatically animate to the fragment at the desired position. Simple.
If you want to add another fragment to the existing FragmentPagerAdapter, then you'll need to first add the fragment's instance to that adapter and then call notifiyDataSetChanged on it.
I have two fragments, I need to keep them both but show and hide on button clicks.
I added the first fragment using:
FragmentTransaction transaction = getSupportFragmentManager()
.beginTransaction();
mDishFragment = new DishFragment();
transaction.add(R.id.dish_fragment, mDishFragment, "DishFragment");
transaction.commit();
First fragment (DishFragment) has a button on clicking of which the code checks if "OrderSummaryFragment" exists(using findFragmentbyTag), if it does, it should show() it else add() a new one. here is the code:
FragmentTransaction transaction = getSupportFragmentManager()
.beginTransaction();
if (getFragmentManager().findFragmentByTag("OrderSummaryFragment") == null) {
System.out.println("OrderSummaryFragment not found");
transaction.add(R.id.dish_fragment, mOrderSummaryFragment,"OrderSummaryFragment");
System.out.println("Orderfragment added");
transaction.addToBackStack(null);
transaction.commit();
}else{
System.out.println("OrderSummaryFragment found");
transaction.hide(mDishFragment);
transaction.show(mOrderSummaryFragment);
transaction.commit();
}
For the first time since "OrderSummaryFragment" doesn't exist, the code adds one and it is displayed. There is a back button on the "OrderSummaryFragment" pressing of which show() up the first fragment "DishFragment".
The second time, since we have already added the "Ordersummaryfragment" previously, the findFragmentByTag should return OrderSummaryFragment but it returns null instead.
Note: I am not using replace() cause I want to reuse both of these fragments.
Hope someone can help me out.
Your fragment should search for your fragments using the getSupportFragmentManager() instead of the getFragmentManager Method() in your if structure.
BTW, What is that R.id.dish_fragment object? A fragment? A container? It should be a container like a LinearLayout.
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().
FragmentManager fm = getSupportFragmentManager();
Fragment Home = fm.findFragmentByTag("Home");
Fragment rec = fm.findFragmentByTag("Recents");
Fragment search = fm.findFragmentByTag("Search");
I am trying to get the current fragmenTag like this, i am checking whether its loaded or not. The condition inside does not execute at all. Am i doing the right way.
if(Home != null){
// Do the following
}
You can check whether your current fragment is visible or not by following:
if (Home.isVisible()) {
// write your "home" fragment code here
}