How to use PlaceAutoCompleteFragment widget in a Fragment - android

I am using PlaceAutoCompleteFragment inside a Fragment. First time when Fragment(App fragment in which PlaceAutoCompleteFragment is placed) opens it works fine like a charm.
But, then second time I hit button to open Fragment it crashes with below error. It works only a single time.
FATAL EXCEPTION:
android.view.InflateException: Binary XML file line #64: Error
inflating class fragment Caused by:
java.lang.IllegalArgumentException: Binary XML file line #64:
Duplicate id 0x7f0d0094, tag null, or parent id 0xffffffff with
another fragment for
com.google.android.gms.location.places.ui.PlaceAutocompleteFragment
This is how I am using this,for Search location
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.parkingview_fragment, container, false);
mapFragment = (SupportMapFragment) this.getChildFragmentManager().findFragmentById(R.id.map_parkingview);
mapFragment.getMapAsync(this);
// For Search location
PlaceAutocompleteFragment autocompleteFragment = null;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
autocompleteFragment = (PlaceAutocompleteFragment) getActivity().getFragmentManager().findFragmentById(R.id.place_fragment_parkingview);
}
autocompleteFragment.setOnPlaceSelectedListener(this);
autocompleteFragment.setHint("Search a Location");
// autocompleteFragment.setBoundsBias(BOUNDS_MOUNTAIN_VIEW);
return view;
}
XML:
<fragment
android:id="#+id/place_fragment_parkingview"
android:name="com.google.android.gms.location.places.ui.PlaceAutocompleteFragment"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>

Declare your fragment Dynamically it will solve the issue.
<FrameLayout
android:id="#+id/fragment_content"
android:layout_width="match_parent"
android:layout_height="wrap_content"
/>
And Update your fragment onCreateView
SupportPlaceAutocompleteFragment autocompleteFragment = new SupportPlaceAutocompleteFragment();
android.support.v4.app.FragmentManager fm = getFragmentManager();
FragmentTransaction ft = fm.beginTransaction();
ft.replace(R.id.fragment_content, autocompleteFragment);
ft.commit();

This problem is caused because you haven't removed yet the PlaceAutoCompleteFragment instance created before at some point.
Careful guys! If you use the method posted by Jordon, it will work, but the fragment's views (the input edittext, and the clearbutton for example) won't be accesible because the fragment's views aren't created yet...the correct answer is REMOVE the instance of the fragment putted in the xml file, programmatically, overwriting the onDestroyView method on the Fragment containing the PlaceAutoCompleteFragment.
#Override
public void onDestroyView() {
if (autocompleteFragment != null) {
android.support.v4.app.FragmentTransaction fragmentTransaction = getChildFragmentManager().beginTransaction();
fragmentTransaction.remove(autocompleteFragment).commitNowAllowingStateLoss();
}
super.onDestroyView();
}
This way, anytime you recreate your Fragment it won't have an instance of the PlaceAutoCompleteFragment already created. Happy Coding!

I was using-
<fragment
android:id="#+id/location_autocomplete_fragment"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#drawable/plain_border"
android:name="com.google.android.gms.location.places.ui.PlaceAutocompleteFragment" />
inside my fragment layout file and initializing it using-
PlaceAutocompleteFragment locationAutocompleteFragment = (PlaceAutocompleteFragment)
getActivity().getFragmentManager()
.findFragmentById(R.id.location_autocomplete_fragment);
I switched to-
<fragment
android:id="#+id/location_autocomplete_fragment"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#drawable/plain_border"
android:name="com.google.android.gms.location.places.ui.SupportPlaceAutocompleteFragment" />
and initialisation by-
SupportPlaceAutocompleteFragment locationAutocompleteFragment = (SupportPlaceAutocompleteFragment)
getChildFragmentManager()
.findFragmentById(R.id.location_autocomplete_fragment);

Related

Replaced fragment still visible behind new fragment

I try to implement an activity which can load different fragments into one container view element. I follow the Building a Flexible UI Training. Problem: When replacing a fragment, I can still see the replaced fragment in the background.
I see that my question has already been asked numerous times. However all the answers I found seem to be just a workaround (setting the background-color of fragments) or do not apply.
Here is what I have setup so far:
The activity's XML layout contains one FrameLayout as a container for the fragments:
<FrameLayout
android:id="#+id/fragment_container"
android:layout_width="match_parent"
android:layout_height="match_parent" />
The id fragment_container is used nowhere else in the project.
The complete XML layout of the first fragment:
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="First Fragment" />
The complete XML layout of the second fragment:
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:textColor="#ff0000"
android:text="Fragment Second" />
The class file of the first fragment looks like this (class for second fragment analogous):
public class FirstFragment extends Fragment {
public FirstFragment() {}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_first, container, false);
}
}
In the activity's onCreate method I load the first fragment:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
// load first fragment
if (savedInstanceState == null) {
getSupportFragmentManager().beginTransaction()
.add(R.id.fragment_container, new FirstFragment())
.commit();
}
}
When selecting a menu item I try to replace the first fragment with the second fragment with this code in the activity's onOptionsItemSelected method:
getFragmentManager().beginTransaction()
.replace(R.id.fragment_container, new SecondFragment())
.addToBackStack(null) // <-- does not make any difference if left out
.commit();
The result is that the text "Fragment Second" is printed in red above the text "First Fragment".
What is the "right way" (i.e. not just setting a background-color) to fix this problem?
I noticed this in onCreate:
getSupportFragmentManager()
and this in onOptionsItemSelected:
getFragmentManager()
There are actually both versions of the FragmentManager in AppCompatActivity and they know nothing about each other. So when you tell android.app.FragmentManager to replace a fragment that was added by android.support.v4.app.FragmentManager, it doesn't know anything about a FirstFragment so the operation acts more like an add than a replace.
I've made this mistake more than once. You'll need to comb through your code and make sure you are consistent about using the support class vs. the regular class.

Binary XML file line #21: Error inflating class fragment

I have a map fragment class and I added a button on top of it. When I click on it I am calling another fragment class with a simple textview and save button. When save is clicked I want to go back to my mapfragment class. Right now it is throwing an error when I click save and go back. The error is when it is inflating the class > Just wondering if I am doing anything wrong while popping from the backstack. I just want to remove the last one and go back to my map.
My map layout is as follows:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<fragment
android:id="#+id/map"
android:name="com.google.android.gms.maps.MapFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scrollbars="vertical">
</fragment>
</LinearLayout>
MapFragment is as follows:
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.maplayout,container,false);
return v;
}
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
FragmentManager fm = getChildFragmentManager();
fragment = (MapFragment) fm.findFragmentById(R.id.map);
if (fragment == null) {
fragment = MapFragment.newInstance();
fm.beginTransaction().replace(R.id.map, fragment).commit();
}
}
The back method:
FragmentManager fm = getActivity().getFragmentManager();
fm.popBackStack("TEXT_FRAGMENT", FragmentManager.POP_BACK_STACK_INCLUSIVE);
fm.beginTransaction()
.replace(R.id.map_tab,
mapFragment,
"maptab")
.addToBackStack("maptab")
.commit();
The error is: Fragment does not have a view.
The map_tab is the tab on which MapFragment was added. The map fragment is added on top of this.
EDIT: In the back method I added fm.popBackStack("TEXT_FRAGMENT", FragmentManager.POP_BACK_STACK_INCLUSIVE
but then this gives me the error when I go back to my Map Fragment and on inflating I get the error.
Don't commit a new Fragment. Instead,
Look at the getFragmentManager().popBackStack() methods (there are several to choose from)
http://developer.android.com/reference/android/app/FragmentManager.html#popBackStack()
Got it to work finally. Had to remove the mapfragment before adding a new fragment.

java.lang.IllegalArgumentException: No view found for id 0x1020002 (android:id/content) for fragment

I am trying to move from one fragment to another.. It shows following error during fragment transaction-
java.lang.IllegalArgumentException: No view found for id 0x1020002 (android:id/content) for fragment PhotosFragment2{41a57218 #3 id=0x1020002}
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:930)
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1115)
at android.support.v4.app.BackStackRecord.run(BackStackRecord.java:682)
at android.support.v4.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1478)
at android.support.v4.app.FragmentManagerImpl$1.run(FragmentManager.java:446)
at android.os.Handler.handleCallback(Handler.java:615)
at android.os.Handler.dispatchMessage(Handler.java:92)
at android.os.Looper.loop(Looper.java:153)
at android.app.ActivityThread.main(ActivityThread.java:5086)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:511)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:821)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:584)
at dalvik.system.NativeStart.main(Native Method)
Below are the classes.I have used following code for fragment transaction
Fragment fragment = new PhotosFragment2();
FragmentTransaction fragmentTransaction = getFragmentManager().beginTransaction();
fragmentTransaction.replace(android.R.id.content, fragment);
fragmentTransaction.commit();
PhotosFragment.java
public class PhotosFragment extends Fragment {
private FragmentActivity myContext;
#Override
public void onAttach(Activity activity) {
myContext = (FragmentActivity) activity;
super.onAttach(activity);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.photos, container, false);
rootView.setVerticalScrollBarEnabled(false);
int[] mThumbIds = {
R.drawable.album8, R.drawable.album3,
R.drawable.album4, R.drawable.album8,
R.drawable.album6, R.drawable.album7,
R.drawable.album12, R.drawable.album10,
};
int[] mThumbIds2 = {
R.drawable.album8, R.drawable.album3,
R.drawable.album4,
R.drawable.album6, R.drawable.album7,
R.drawable.album9, R.drawable.album10,
R.drawable.album11, R.drawable.album12, R.drawable.album8,
R.drawable.album8, R.drawable.album3,
R.drawable.album4,
R.drawable.album6, R.drawable.album7,
R.drawable.album9, R.drawable.album10,
R.drawable.album11, R.drawable.album12, R.drawable.album8,
};
CustomGridSingle2 adapter = new CustomGridSingle2(myContext, mThumbIds);
GridView grid = (GridView)rootView.findViewById(R.id.gridView);
final ImageView img= (ImageView)rootView.findViewById(R.id.imageView7);
grid.setFocusable(false);
grid.setAdapter(adapter);
grid.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Fragment fragment = new PhotosFragment2();
FragmentTransaction fragmentTransaction = getFragmentManager().beginTransaction();
fragmentTransaction.replace(android.R.id.content, fragment);
fragmentTransaction.commit();
}
});
CustomGridSingle2 adapter2 = new CustomGridSingle2(myContext, mThumbIds2);
GridView grid2 = (GridView)rootView.findViewById(R.id.gridView2);
grid2.setFocusable(false);
grid2.setAdapter(adapter2);
grid2.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Fragment fragment = new PhotosFragment2();
FragmentTransaction fragmentTransaction = getFragmentManager().beginTransaction();
fragmentTransaction.replace(android.R.id.content, fragment);
fragmentTransaction.commit();
}
});
return rootView;
}
}
PhotosFragment2.java
public class PhotosFragment2 extends Fragment {
private FragmentActivity myContext;
#Override
public void onAttach(Activity activity) {
myContext = (FragmentActivity) activity;
super.onAttach(activity);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
View rootView = inflater.inflate(R.layout.photos2, container, false);
myContext.getActionBar().hide();
return rootView;
}
}
Activity xml file
<android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent">
<FrameLayout
android:id="#+id/frame_container"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<LinearLayout
android:id="#+id/left_drawer_view"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="start"
android:background="#drawable/bgmenu"
android:orientation="vertical">
<RelativeLayout
android:id="#+id/profilelayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="0"
android:paddingTop="10dp">
<ImageView
android:id="#+id/drawer_profile_image"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignBottom="#+id/drawer_profile_background"
android:layout_alignLeft="#+id/drawer_profile_background"
android:layout_alignRight="#+id/drawer_profile_background"
android:layout_alignTop="#+id/drawer_profile_background"
android:layout_marginBottom="7.667dp"
android:layout_marginLeft="6.5dp"
android:layout_marginRight="8.3dp"
android:layout_marginTop="7.667dp"
android:scaleType="centerCrop"></ImageView>
<ImageView
android:id="#+id/drawer_profile_background"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:scaleType="centerCrop"
android:src="#drawable/profileblock">
</ImageView>
<ImageView
android:id="#+id/settingicon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignBottom="#+id/drawer_profile_background"
android:layout_marginLeft="-15dp"
android:layout_toRightOf="#+id/drawer_profile_background"
android:background="#drawable/settings" />
<textview
android:id="#+id/username"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="#+id/drawer_profile_background"
android:layout_centerHorizontal="true"
android:layout_marginTop="5dp"
android:text="Name"
android:textAppearance="?android:attr/textAppearanceListItemSmall"
android:textColor="#android:color/white" />
</RelativeLayout>
<ListView
android:id="#+id/list_slidermenu"
style="#style/buttonStyle"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_marginTop="30dp"
android:layout_weight="2"
android:cacheColorHint="#android:color/transparent"
android:choiceMode="singleChoice"
android:divider="#android:color/transparent"
android:dividerHeight="1dp"
android:listSelector="#android:color/transparent"
android:scrollbars="none" />
</LinearLayout>
</android.support.v4.widget.DrawerLayout>
When you use fragmentTransaction.replace(R.id.container,fragment) it will remove any fragments that are already in the container and add your new one to the same container.
Now i can suggest you 2 things.First, if you want to use fragmentTransaction.replace(android.R.id.content, fragment); which you are doing right now,then don't set content for your Activity using setContentView.This should work fine then.To know what exactly android.R.id.content is you can refer this stackoverflow question and answer
Or Secondly, In the layout of your Activity have a FrameLayout whose id is content. And then use
fragmentTransaction.replace(R.id.content, fragment);
fragmentTransaction.addToBackStack(null);//add the transaction to the back stack so the user can navigate back
// Commit the transaction
fragmentTransaction.commit();
Hope this helps.
More Info:
From your comments it seems that you are having some problem in getting the idea of using FrameLayout in your Activity's layout(Not of any of the Fragment's layout).From the Documents
FrameLayout is designed to block out an area on the screen to display a single item. Generally, FrameLayout should be used to hold a single child view, because it can be difficult to organize child views in a way that's scalable to different screen sizes without the children overlapping each other.
So the main purpose of FrameLayout is to block the area required to fit the largest child view. If you use a FrameLayout as Fragment Container you can ensure that you always have the space available to accommodate the largest Fragment's layout.
So you can have your FrameLayout something like this in your Activity's layout xml file
<FrameLayout
android:id="#+id/content"
android:layout_height="match_parent"
android:layout_width="match_parent">
<!--you can put your existing views of your current xml here, so yes your entire xml is now inside this FrameLayout -->
</FrameLayout>
I don't use getSupportFragmentManager().
I use getChildFragmentManager() and it worked for me.
You can try it.
If you are trying to put Fragment into Fragment, use getChildFragmentManager()
If you are using ViewPager, use getChildFragmentManager() for pager adapter
viewPager.setAdapter(new ItemsAdapter(getChildFragmentManager()));
You have to set a content view in your Activity that your PhotosFragment is attached.
protected void onCreate(Bundle bundle) {
super.onCreate(bundle);
setContentView(R.layout.activity_main);
//...
}
i know this is very late. But it may work for other's.
I declared the id for each layout, like (3rd line bellow)
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/container"
Since Android 4.2 (API 17) nested fragments become avaliable.
See this
To place fragment inside other fragment use getChildFragmentManager()
Also available in support library.
I had the same error and after trying a lot of things I found that the problem was with the "id" and "getActivity().getSupportFragmentManager()".
Before i implement i like these
txt_more.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
getChildFragmentManager()
.beginTransaction()
.replace(R.id.content_frame, new OpportunitiesFragment())
.commit(); }
});
Then i changed to these
txt_more.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
## Heading ##
getActivity().getSupportFragmentManager()
.beginTransaction()
.replace(android.R.id.content, new OpportunitiesFragment())
.commit(); }
});
Put this block of code in PhotosFragment2 onCreateView method:
View rootView = inflater.inflate(R.layout.photos2, null);
instead of:
View rootView = inflater.inflate(R.layout.photos2, container, false);
in my case I had to change
ViewGroup root = (ViewGroup) inflater.inflate(R.layout.sample,
container);
to
ViewGroup root = (ViewGroup) inflater.inflate(R.layout.sample,
container, false);
This answer highlights a silly mistake that may occur, that arises when nesting fragments or you are converting activities to fragments.
If you are trying to replace a fragment within a fragment with the fragmentManager but you are not inflating the parent fragment that can cause an issue.
In BaseFragment.java OnCreateView:
if (savedInstanceState == null) {
getFragmentManager().beginTransaction()
.replace(R.id.container, new DifferentFragment())
.commit();
}
return super.onCreateView(inflater, container, savedInstanceState);
Replace super.onCreateView(inflater, container, savedInstanceState);
with inflating the correct layout for the fragment:
return inflater.inflate(R.layout.base_fragment, container, false);
The problem may be that you add a fragment and beginTransaction in some fragment like
getFragmentManager().beginTransaction().replace(android.R.id.content, ImageBrowseFragment.newInstance(bundle),"ImageBrowseFragment")
.addToBackStack(null).commit();
I just change getFragmentManager() to getActivity().getSupportFragmentManager()
Then everything goes fine
When you add a fragment in a fragment use android.R.id.content Or Window.ID_ANDROID_CONTENT,I guess it represents the root container of your fragment not the activity. So change to getActivity().getSupportFragmentManager() works it out
If you use ViewPager with fragments (pages) and try to show a new fragment from a page, you will get this error. I think, you cannot reference to a container of an Activity from a ViewPager's page.
In this case you should call getActivity(). Then in Activity write a method that will open a new fragment.
class YourActivity : AppCompatActivity() {
fun showNewFragment(title: String) {
val fm = supportFragmentManager
fm?.beginTransaction()?.apply {
val fragment = NewFragment.newInstance(title)
replace(R.id.container, fragment, NewFragment.TAG)
addToBackStack(null)
}?.commit()
}
}
class PageFragment : Fragment() {
private fun show() {
(activity as YourActivity).showNewFragment("New fragment")
}
}
If you call getParentFragment() and add a new fragment, then you will place a new fragment inside ViewPager:
class ViewPagerFragment : Fragment() {
fun showNewFragment(title: String) {
val fm = childFragmentManager
fm?.beginTransaction()?.apply {
val fragment = NewFragment.newInstance(title)
replace(R.id.container, fragment, NewFragment.TAG)
addToBackStack(null)
}?.commit()
}
}
class PageFragment : Fragment() {
private fun show() {
(parentFragment as? ViewPagerFragment)?.showNewFragment("New fragment")
}
}
Make sure the fragment id you are calling is in the class listed in setcontent in onCreate method. For my case, I was editing the layout from linear to constraint. So as not to mess with the working code, I made another layout but messed an id in the process so that what was on oncreate was the edited layout but the fragment being called was from the old layout. Apparently, in the new layout I gave it a different id name. Search the id of your fragment using ctrl+shift+f and see if the search results point to the layout you specified in the oncreate method. Goodluck.
The most common mistake that can be happened is, If you have more than one version of XML layout (let say v21 and v23) and you added <fragment> tag in lower version of XML only (or vice-versa).
So, please check you added <fragment> tag (or pageGroup, etc) in both of the versions.
You are trying to open fragment which fragmentContainer(the view in which you are trying to open fragment) is one or more level above from your current fragmentContainer.
Try to change your fragment hierarchy architecture.

MapFragment inside a fragment, app crash on reopening fragment

i have a mapfragment inside another fragment
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent" >
<fragment
android:id="#+id/map"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:name="com.google.android.gms.maps.MapFragment"
/>
</FrameLayout>
and im initializing map in oncreateview
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
view = inflater.inflate(R.layout.event_fragment, null);
try{
events = new ArrayList<EventsModel>();
try {
initilizeMap();
} catch (Exception e) {
e.printStackTrace();
}
double latitude = 24.875419;
double longitude = 66.993293;
CameraPosition cameraPosition = new CameraPosition.Builder().target(
new LatLng(latitude, longitude)).zoom(12).build();
map.animateCamera(CameraUpdateFactory.newCameraPosition(cameraPosition));
loadEvents().execute();
}catch(Exception e){
}
return view;
}
its working fine but when i press back button and reopen this fragment it crashes
04-19 21:18:21.803: E/AndroidRuntime(31612): Caused by: java.lang.IllegalArgumentException: Binary XML file line #6: Duplicate id 0x7f050006, tag null, or parent id 0xffffffff with another fragment for com.google.android.gms.maps.MapFragment
then i googled it and put it in ondestroy
Fragment fragment = (getFragmentManager().findFragmentById(R.id.map));
FragmentTransaction ft = getActivity().getSupportFragmentManager().beginTransaction();
ft.remove(fragment);
ft.commit();
the above problem is resolved bu now it gives me nullpointer on reopening the fragment that had mapfragment in it may be because i removed it with above code but whats the solution now?
Please make sure that you have correctly checked the condition where map inflated is null or not while creating view for map fragment or while destroying.
put this one on onDestroy() method
SupportMapFragment mapFragment = ((SupportMapFragment)
getActivity().getSupportFragmentManager().findFragmentById(R.id.map_location_sharing));
if(mapFragment != null) {
FragmentManager fM = getFragmentManager();
fM.beginTransaction().remove(mapFragment).commit();

Fragment duplication on Fragment Transaction

Ok, whenever I try to replace a fragment in my application, it only adds the fragment inside of the container the other fragment is, and leaves the current fragment. I've tried calling replace and referencing the view the contains the fragment, and by referencing the fragment itself. Neither of these work. I can add a fragment to a view with the fragment transaction manager, but even if I try to remove it after its been added, it doesn't work. Any help would be appreciated. Here are my files.
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
//Setup the actionabar. Use setDrawableBackground to set a background image for the actionbar.
final ActionBar actionbar = getActionBar();
actionbar.setDisplayShowTitleEnabled(false);
actionbar.setDisplayUseLogoEnabled(true);
actionbar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
actionbar.addTab(actionbar.newTab().setText(R.string.home_tab_text).setTabListener(this),true);
actionbar.addTab(actionbar.newTab().setText(R.string.insert_tab_text).setTabListener(this));
Fragment fragment = new insert_button_frag();
FragmentTransaction transaction = getFragmentManager().beginTransaction();
transaction.replace(R.id.button_fragment, fragment);
transaction.addToBackStack(null);
transaction.commit();
}
Here is the layout
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<LinearLayout
android:orientation="vertical"
android:id="#+id/button_fragment_container"
android:layout_width="fill_parent"
android:layout_height="wrap_content" >
<fragment
android:name="com.bv.silveredittab.home_button_frag"
android:id="#+id/button_fragment"
android:layout_width="fill_parent"
android:layout_height="wrap_content" />
</LinearLayout>
<LinearLayout
android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="fill_parent" >
<fragment
android:name="com.bv.silveredittab.quick_insert_frag"
android:id="#+id/quick_insert_frag"
android:layout_width="350dip"
android:layout_height="fill_parent" />
<fragment
android:name="com.bv.silveredittab.editor_frag"
android:id="#+id/editor_frag"
android:layout_width="fill_parent"
android:layout_height="fill_parent" />
</LinearLayout>
</LinearLayout>
And here is the fragment code
public class insert_button_frag extends Fragment {
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
return inflater.inflate(R.layout.insert_buttons,container, false);
}
}
Like I have said. I have tried referencing the fragments parent view to replace it, and the fragment itself (by id) and still, it only adds the new fragment, inside the containing view the original fragment is in.
I solved this by using a placeholder in my Layout and then attaching my Fragment to it at runtime.
Like you, if I instantiated my Fragment within my xml layout then the contents would remain visible after replacing it with another Fragment at runtime.
The problem is this line:
transaction.replace(R.id.button_fragment, fragment);
replace has two overloaded forms. In both of them, the first argument is the container of the Fragment to be replaced, not the Fragment itself. So, in your case, you need to call
transaction.replace(R.id.button_fragment_container, fragment);
edit: I see in your question that you have tried both. I have tested and verified the behavior. This appears to be a bug in the FragmentTransaction API.
Edit2: not a bug after all. You simply cannot replace fragments added statically in a layout file. You can only replace those you have added programmatically ( Android: can't replace one fragment with another )
I had the same issue. Take a look at this link: Android Fragment Duplication
I wonder if the fact that you're passing the container into the inflater.inflate() method causes it to create the new fragment inside of the old one instead of a wholesale replace. I've been providing 'null' to my inflaters in the working version.
Here's the essentials from the version I have working...
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState){
View newFrag = new View(getActivity().getApplicationContext());
newFrag = inflater.inflate(R.id.frag, null);
return newFrag;
}
The google developer guide is quite confusing because it shows first to implement hard coded fragment in you xml. But if you really want to replace existing fragment with the new one, then you should add it(the first) at runtime.
What official site state is
FragmentTransaction replace (int containerViewId, Fragment fragment, String tag)
Replace an existing fragment that was added to a container. This is
essentially the same as calling remove(Fragment) for all currently
added fragments that were added with the same containerViewId and then
add(int, Fragment, String) with the same arguments given here.
You should noticed that it says that Replace an existing fragment that was added to container
So, your xml should look like
someActivity.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
...
tools:context="someActivity">
<ImageView
.../>
<LinearLayout
android:id="#+id/fragment_container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:gravity="bottom"/>
</RelativeLayout>
And than in your activity do in OnCreate()
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
[...]
getSupportFragmentManager().beginTransaction()
.add(R.id.fragment_container, new FirstFragment).commit();
}
Than you may easily replace fragment with your animations and event add it to back stack in order to save its state.
private SecondFrag getSecondFrag(){
if(secondFrag == null)
secondFrag = new SecondFrag()
return secondFrag;
}
private void openRechargeFragment(){
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
ft.setCustomAnimations(R.anim.show_frag, R.anim.hide_frag,
R.anim.show_frag, R.anim.hide_frag);
ft.replace(R.id.fragment_container, getSecondFrag(), "myTAG");
ft.addToBackStack(null);
ft.commit();
}

Categories

Resources