Duplicate ID, tag null, or parent id with another fragment for com.google.android.gms.maps.MapFragment

前端 未结 23 1628
-上瘾入骨i
-上瘾入骨i 2020-11-22 00:25

I have an application with three tabs.

Each tab has its own layout .xml file. The main.xml has its own map fragment. It\'s the one that shows up when the application

相关标签:
23条回答
  • 2020-11-22 01:23

    In this solution you do not need to take static variable;

    Button nextBtn;
    
    private SupportMapFragment mMapFragment;
    
    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        super.onCreateView(inflater, container, savedInstanceState);
    
        if (mRootView != null) {
            ViewGroup parent = (ViewGroup) mRootView.getParent();
            Utility.log(0,"removeView","mRootView not NULL");
            if (parent != null) {
                Utility.log(0, "removeView", "view removeViewed");
                parent.removeAllViews();
            }
        }
        else {
            try {
                mRootView = inflater.inflate(R.layout.dummy_fragment_layout_one, container, false);//
            } catch (InflateException e) {
        /* map is already there, just return view as it is  */
                e.printStackTrace();
            }
        }
    
        return  mRootView;
    }
    
    @Override
    public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        FragmentManager fm = getChildFragmentManager();
        SupportMapFragment mapFragment = (SupportMapFragment) fm.findFragmentById(R.id.mapView);
        if (mapFragment == null) {
            mapFragment = new SupportMapFragment();
            FragmentTransaction ft = fm.beginTransaction();
            ft.add(R.id.mapView, mapFragment, "mapFragment");
            ft.commit();
            fm.executePendingTransactions();
        }
        //mapFragment.getMapAsync(this);
        nextBtn = (Button) view.findViewById(R.id.nextBtn);
        nextBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Utility.replaceSupportFragment(getActivity(),R.id.dummyFragment,dummyFragment_2.class.getSimpleName(),null,new dummyFragment_2());
            }
        });
    
    }`
    
    0 讨论(0)
  • 2020-11-22 01:24

    I am a bit late to the party but Non of these answer helped me in my case. I was using Google map as SupportMapFragment and PlaceAutocompleteFragment both in my fragment. As all the answers pointed to the fact that the problem is with SupportMapFragment being the map to be recreated and redrawn.But after digging found out my problem was actually with PlaceAutocompleteFragment

    So here is the working solution for those who are facing this problem because of SupportMapFragment and SupportMapFragment

     //Global SupportMapFragment mapFragment;
     mapFragment = (SupportMapFragment) getChildFragmentManager().findFragmentById(R.id.mapFragment);
        FragmentManager fm = getChildFragmentManager();
    
        if (mapFragment == null) {
            mapFragment = SupportMapFragment.newInstance();
            fm.beginTransaction().replace(R.id.mapFragment, mapFragment).commit();
            fm.executePendingTransactions();
        }
    
        mapFragment.getMapAsync(this);
    
        //Global PlaceAutocompleteFragment autocompleteFragment;
    
    
        if (autocompleteFragment == null) {
            autocompleteFragment = (PlaceAutocompleteFragment) getActivity().getFragmentManager().findFragmentById(R.id.place_autoCompleteFragment);
    
        }
    

    And in onDestroyView clear the SupportMapFragment and SupportMapFragment

    @Override
    public void onDestroyView() {
        super.onDestroyView();
    
    
        if (getActivity() != null) {
            Log.e("res","place dlted");
            android.app.FragmentManager fragmentManager = getActivity().getFragmentManager();
            android.app.FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
            fragmentTransaction.remove(autocompleteFragment);
            fragmentTransaction.commit(); 
           //Use commitAllowingStateLoss() if getting exception 
    
            autocompleteFragment = null;
        }
    
    
    }
    
    0 讨论(0)
  • 2020-11-22 01:25

    The problem is that what you are trying to do shouldn't be done. You shouldn't be inflating fragments inside other fragments. From Android's documentation:

    Note: You cannot inflate a layout into a fragment when that layout includes a <fragment>. Nested fragments are only supported when added to a fragment dynamically.

    While you may be able to accomplish the task with the hacks presented here, I highly suggest you don't do it. Its impossible to be sure that these hacks will handle what each new Android OS does when you try to inflate a layout for a fragment containing another fragment.

    The only Android-supported way to add a fragment to another fragment is via a transaction from the child fragment manager.

    Simply change your XML layout into an empty container (add an ID if needed):

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:id="@+id/mapFragmentContainer"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical" >
    </LinearLayout>
    

    Then in the Fragment onViewCreated(View view, @Nullable Bundle savedInstanceState) method:

    @Override
    public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        FragmentManager fm = getChildFragmentManager();
        SupportMapFragment mapFragment = (SupportMapFragment) fm.findFragmentByTag("mapFragment");
        if (mapFragment == null) {
            mapFragment = new SupportMapFragment();
            FragmentTransaction ft = fm.beginTransaction();
            ft.add(R.id.mapFragmentContainer, mapFragment, "mapFragment");
            ft.commit();
            fm.executePendingTransactions();
        }
        mapFragment.getMapAsync(callback);
    }
    
    0 讨论(0)
  • 2020-11-22 01:25

    I would recommend replace() rather than attach()/detach() in your tab handling.

    Or, switch to ViewPager. Here is a sample project showing a ViewPager, with tabs, hosting 10 maps.

    0 讨论(0)
  • 2020-11-22 01:28

    This is my answer:

    1, Create a layout xml like following:

    <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/map_container"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    </FrameLayout>
    

    2, in the Fragment class, add a google map programmatically.

    import com.google.android.gms.maps.GoogleMap;
    import com.google.android.gms.maps.SupportMapFragment;
    import android.app.Activity;
    import android.os.Bundle;
    import android.support.v4.app.Fragment;
    import android.support.v4.app.FragmentTransaction;
    import android.util.Log;
    import android.view.LayoutInflater;
    import android.view.View;
    import android.view.ViewGroup;
    
    /**
     * A simple {@link android.support.v4.app.Fragment} subclass. Activities that
     * contain this fragment must implement the
     * {@link MapFragment.OnFragmentInteractionListener} interface to handle
     * interaction events. Use the {@link MapFragment#newInstance} factory method to
     * create an instance of this fragment.
     * 
     */
    public class MapFragment extends Fragment {
        // TODO: Rename parameter arguments, choose names that match
        private GoogleMap mMap;
    
        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
        }
    
        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container,
                Bundle savedInstanceState) {
            // Inflate the layout for this fragment
            View view = inflater.inflate(R.layout.fragment_map, container, false);
            SupportMapFragment mMapFragment = SupportMapFragment.newInstance();
            mMap = mMapFragment.getMap();
            FragmentTransaction transaction = getChildFragmentManager().beginTransaction();
            transaction.add(R.id.map_container, mMapFragment).commit();
            return view;
        }
    
        @Override
        public void onAttach(Activity activity) {
            super.onAttach(activity);
            Log.d("Attach", "on attach");
        }
    
        @Override
        public void onDetach() {
            super.onDetach();
        }
    } 
    
    0 讨论(0)
提交回复
热议问题