ID trùng lặp, thẻ null hoặc id cha với một đoạn khác cho com.google.android.gms.maps.MapFragment


333

Tôi có một ứng dụng với ba tab.

Mỗi tab có tệp .xml bố cục riêng. Tệp chính có đoạn bản đồ riêng. Đây là ứng dụng xuất hiện khi ứng dụng lần đầu tiên ra mắt.

Mọi thứ hoạt động tốt, ngoại trừ khi tôi thay đổi giữa các tab. Nếu tôi cố gắng chuyển trở lại tab mảnh bản đồ, tôi sẽ gặp lỗi này. Chuyển sang và giữa các tab khác hoạt động tốt.

Điều gì có thể sai ở đây?

Đây là lớp chính của tôi và tệp chính của tôi, cũng như một lớp có liên quan mà tôi sử dụng (bạn cũng sẽ tìm thấy nhật ký lỗi ở phía dưới)

lớp chính

package com.nfc.demo;

import android.app.ActionBar;
import android.app.ActionBar.Tab;
import android.app.Activity;
import android.app.Fragment;
import android.app.FragmentTransaction;
import android.os.Bundle;
import android.widget.Toast;

public class NFCDemoActivity extends Activity {

    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        ActionBar bar = getActionBar();
        bar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
        bar.setDisplayOptions(0, ActionBar.DISPLAY_SHOW_TITLE);

        bar.addTab(bar
                .newTab()
                .setText("Map")
                .setTabListener(
                        new TabListener<MapFragment>(this, "map",
                                MapFragment.class)));
        bar.addTab(bar
                .newTab()
                .setText("Settings")
                .setTabListener(
                        new TabListener<SettingsFragment>(this, "settings",
                                SettingsFragment.class)));
        bar.addTab(bar
                .newTab()
                .setText("About")
                .setTabListener(
                        new TabListener<AboutFragment>(this, "about",
                                AboutFragment.class)));

        if (savedInstanceState != null) {
            bar.setSelectedNavigationItem(savedInstanceState.getInt("tab", 0));
        }
        // setContentView(R.layout.main);

    }

    @Override
    protected void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        outState.putInt("tab", getActionBar().getSelectedNavigationIndex());
    }

    public static class TabListener<T extends Fragment> implements
            ActionBar.TabListener {
        private final Activity mActivity;
        private final String mTag;
        private final Class<T> mClass;
        private final Bundle mArgs;
        private Fragment mFragment;

        public TabListener(Activity activity, String tag, Class<T> clz) {
            this(activity, tag, clz, null);
        }

        public TabListener(Activity activity, String tag, Class<T> clz,
                Bundle args) {
            mActivity = activity;
            mTag = tag;
            mClass = clz;
            mArgs = args;

            // Check to see if we already have a fragment for this tab,
            // probably from a previously saved state. If so, deactivate
            // it, because our initial state is that a tab isn't shown.
            mFragment = mActivity.getFragmentManager().findFragmentByTag(mTag);
            if (mFragment != null && !mFragment.isDetached()) {
                FragmentTransaction ft = mActivity.getFragmentManager()
                        .beginTransaction();
                ft.detach(mFragment);
                ft.commit();
            }
        }

        public void onTabSelected(Tab tab, FragmentTransaction ft) {
            if (mFragment == null) {
                mFragment = Fragment.instantiate(mActivity, mClass.getName(),
                        mArgs);
                ft.add(android.R.id.content, mFragment, mTag);
            } else {
                ft.attach(mFragment);
            }
        }

        public void onTabUnselected(Tab tab, FragmentTransaction ft) {
            if (mFragment != null) {
                ft.detach(mFragment);
            }
        }

        public void onTabReselected(Tab tab, FragmentTransaction ft) {
            Toast.makeText(mActivity, "Reselected!", Toast.LENGTH_SHORT)
                         .show();
        }
    }

}

tệp chính

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

    <fragment
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:id="@+id/mapFragment"
        android:name="com.google.android.gms.maps.MapFragment"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />
</LinearLayout>

lớp có liên quan (MapFragment.java)

package com.nfc.demo;

import android.app.Fragment;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

public class MapFragment extends Fragment {

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {
        super.onCreateView(inflater, container, savedInstanceState);
        return inflater.inflate(R.layout.main, container, false);
    }

    public void onDestroy() {
        super.onDestroy();
    }
}

lỗi

android.view.InflateException: Binary XML file line #7: 
     Error inflating class fragment
   at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:704)
   at android.view.LayoutInflater.rInflate(LayoutInflater.java:746)
   at android.view.LayoutInflater.inflate(LayoutInflater.java:489)
   at android.view.LayoutInflater.inflate(LayoutInflater.java:396)
   at com.nfc.demo.MapFragment.onCreateView(MapFragment.java:15)
   at android.app.Fragment.performCreateView(Fragment.java:1695)
   at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:885)
   at android.app.FragmentManagerImpl.attachFragment(FragmentManager.java:1255)
   at android.app.BackStackRecord.run(BackStackRecord.java:672)
   at android.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1435)
   at android.app.FragmentManagerImpl$1.run(FragmentManager.java:441)
   at android.os.Handler.handleCallback(Handler.java:725)
   at android.os.Handler.dispatchMessage(Handler.java:92)
   at android.os.Looper.loop(Looper.java:137)
   at android.app.ActivityThread.main(ActivityThread.java:5039)
   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:793)
   at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:560)
   at dalvik.system.NativeStart.main(Native Method)

Caused by: java.lang.IllegalArgumentException: 
     Binary XML file line #7: Duplicate id 0x7f040005, tag null, or 
     parent id 0xffffffff with another fragment for 
     com.google.android.gms.maps.MapFragment
   at android.app.Activity.onCreateView(Activity.java:4722)
   at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:680)
   ... 19 more

hãy thử điều này - return super.onCreateView (Inflater, container, yetInstanceState); thay vì super.onCreateView (Inflater, container, yetInstanceState); return Inflater.inflate (R.layout.main, container, false);
Nik

bạn shuold không thêm bạn đoạn khi được lưuInstanceState không null.
muyiou

Hãy xem để bình luận này. Nó có thể giúp bạn: stackoverflow.com/questions/15562416/...
Oleksandr

2
Hãy thay đổi câu trả lời được chấp nhận! Bạn đã chọn một câu trả lời rất xấu mà tạo ra rò rỉ bộ nhớ! Câu trả lời đúng là đây: stackoverflow.com/a/19815266/902276
Daniele Segato

Câu trả lời:


400

Câu trả lời Matt gợi ý các công trình, nhưng nó khiến bản đồ được tái tạo và vẽ lại, điều không phải lúc nào cũng mong muốn. Sau rất nhiều thử và sai, tôi tìm thấy một giải pháp mà làm việc cho tôi:

private static View view;

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    if (view != null) {
        ViewGroup parent = (ViewGroup) view.getParent();
        if (parent != null)
            parent.removeView(view);
    }
    try {
        view = inflater.inflate(R.layout.map, container, false);
    } catch (InflateException e) {
        /* map is already there, just return view as it is */
    }
    return view;
}

Để đo lường tốt, đây là "map.xml" (R.layout.map) với R.id.mapFragment (android: id = "@ + id / mapFragment"):

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

    <fragment xmlns:android="http://schemas.android.com/apk/res/android"
        android:id="@+id/mapFragment"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        class="com.google.android.gms.maps.SupportMapFragment" />
</LinearLayout>

Tôi hy vọng điều này có ích, nhưng tôi không thể đảm bảo rằng nó không có bất kỳ tác dụng phụ nào.

Chỉnh sửa: Có một số tác dụng phụ, chẳng hạn như khi thoát khỏi ứng dụng và khởi động lại. Vì ứng dụng không nhất thiết phải tắt hoàn toàn (nhưng chỉ cần đặt ở chế độ nền), mã trước đó tôi đã gửi sẽ thất bại khi khởi động lại ứng dụng. Tôi đã cập nhật mã thành thứ gì đó phù hợp với mình, cả vào và ra khỏi bản đồ, thoát ra và khởi động lại ứng dụng, tôi không hài lòng lắm với bit thử, nhưng có vẻ như nó hoạt động đủ tốt. Khi nhìn vào dấu vết ngăn xếp, tôi nhận ra rằng tôi có thể kiểm tra xem mảnh bản đồ có trong FragmentManager không, không cần khối thử bắt, mã được cập nhật.

Chỉnh sửa thêm: Hóa ra bạn cần thử đó sau tất cả. Chỉ cần kiểm tra các mảnh bản đồ hóa ra không hoạt động tốt như vậy sau tất cả. Blergh.


25
Đây là một câu trả lời sai -1! Bạn đang rò rỉ một hoạt động bằng cách sử dụng công cụ sửa đổi tĩnh cho Chế độ xem. Nguyên nhân sâu xa của vấn đề này có lẽ là một hoạt động bị rò rỉ khác, đó không thể là rác được thu thập vì bạn đang giữ một tham chiếu mạnh mẽ chỉ ra nó. Trong trường hợp bị ném InflateException, bạn đang sử dụng chế độ xem có bối cảnh hoạt động bị phá hủy! Tốt hơn nên tìm rò rỉ bộ nhớ khác trong ứng dụng của bạn, điều này sẽ giải quyết tất cả các vấn đề.
tomrozb

1
Tôi đoán chúng ta có thể sử dụng WeakReference để tránh rò rỉ bộ nhớ?
Desmond Lua

2
Điều này làm việc cho tôi quá +1. Bạn không bắt buộc phải sử dụng tham chiếu tĩnh của chế độ xem
Karol ygłowicz

4
Đừng làm điều này !!! Nó gây rò rỉ bộ nhớ. Lý do duy nhất điều này xảy ra là vì bạn đang thổi phồng một đoạn từ XML bên trong một đoạn khác. Bạn KHÔNG phải làm điều đó! Bạn nên sử dụng ChildFragmentManager và thêm đoạn trong onViewCreated ()!
Daniele Segato

1
Vâng, điều này thực sự sẽ rò rỉ các hoạt động. Tìm thấy một giải pháp làm việc trong stackoverflow.com/a/27592123/683763 . Ý tưởng là tự gỡ bỏ phương thức SupportMapFragmenttrong onDestroyView.
ULazdins

277

Vấn đề là những gì bạn đang cố gắng không nên làm. Bạn không nên thổi phồng những mảnh vỡ bên trong những mảnh khác. Từ tài liệu của Android :

Lưu ý: Bạn không thể thổi phồng bố cục thành một đoạn khi bố cục đó bao gồm <đoạn>. Các đoạn lồng nhau chỉ được hỗ trợ khi được thêm vào một đoạn động.

Mặc dù bạn có thể hoàn thành nhiệm vụ với các bản hack được trình bày ở đây, tôi khuyên bạn không nên làm điều đó. Không thể chắc chắn rằng những bản hack này sẽ xử lý những gì mỗi hệ điều hành Android mới làm khi bạn cố gắng tăng bố cục cho một đoạn có chứa một đoạn khác.

Cách duy nhất được Android hỗ trợ để thêm một đoạn vào một đoạn khác là thông qua một giao dịch từ người quản lý đoạn con.

Chỉ cần thay đổi bố cục XML của bạn thành một thùng chứa trống (thêm ID nếu cần):

<?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>

Sau đó, trong onViewCreated(View view, @Nullable Bundle savedInstanceState)phương thức Fragment :

@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);
}

4
Xem stackoverflow.com/questions/13733299/ Khăn để biết ví dụ về việc tạo một mảnh bản đồ theo chương trình và khởi tạo bản đồ.
Kristopher Johnson

1
Đồng thời xem stackoverflow.com/questions/19239175/ Ấn để tìm cách khắc phục lỗi rõ ràng trong hỗ trợ phân đoạn con.
Kristopher Johnson

Tôi đã gặp vấn đề này 4.3khi sử dụng một SupportMapFragmentđịnh nghĩa trong XML. Tự động tạo ra các đoạn và đưa nó vào một khung nhìn container đã giải quyết vấn đề. Xem câu trả lời SO này .
theblang

Câu trả lời rất hữu ích. Làm thế nào chúng ta có thể thực hiện một cuộc gọi lại đến hàm chính onCreate ()?
Utopia

2
Theo tài liệu, sử dụng SupportMapFragment.newInstance(); developers.google.com/maps/documentation/android-api/map
Jemshit Iskenderov

178

Tôi đã có cùng một vấn đề và đã có thể giải quyết nó bằng cách loại bỏ thủ công MapFragmenttrong onDestroy()phương thức của Fragmentlớp. Đây là mã hoạt động và tham chiếu MapFragmenttheo ID trong XML:

@Override
public void onDestroyView() {
    super.onDestroyView();
    MapFragment f = (MapFragment) getFragmentManager()
                                         .findFragmentById(R.id.map);
    if (f != null) 
        getFragmentManager().beginTransaction().remove(f).commit();
}

Nếu bạn không xóa MapFragmentthủ công, nó sẽ treo xung quanh để không tốn nhiều tài nguyên để tạo lại / hiển thị lại chế độ xem bản đồ. Có vẻ như việc giữ bên dưới MapViewlà tuyệt vời để chuyển đổi qua lại giữa các tab, nhưng khi được sử dụng trong các đoạn, hành vi này gây ra một bản sao MapViewđược tạo trên mỗi cái mới MapFragmentcó cùng ID. Giải pháp là loại bỏ thủ công MapFragmentvà do đó tạo lại bản đồ cơ bản mỗi khi đoạn bị thổi phồng.

Tôi cũng lưu ý điều này trong một câu trả lời khác [ 1 ].


Nó làm cho ứng dụng bị sập khi nhấp vào nút home của thiết bị, với "Không giữ hoạt động" trong tùy chọn nhà phát triển.
Tháng Bảy

23
điều này hoạt động, nhưng nếu tôi xoay màn hình, ứng dụng của tôi gặp sự cố với ngoại lệ này: Nguyên nhân bởi: java.lang.IllegalStateException: Không thể thực hiện hành động này sau khi onSaveInstanceState
jramoyo

1
Đối với những người có thể quan tâm, bạn có thể loại bỏ ngoại lệ gây ra bởi xoay màn hình bằng cách lưu trữ hướng inital trong hàm tạo của đoạn và chỉ gọi giao dịch trên nếu định hướng KHÔNG thay đổi. Nếu nó đã được thay đổi, không cần phải vật lộn với ID trùng lặp, bởi vì nó không ở đó khi chế độ xem được tạo lại sau khi xoay. Tôi có thể chỉnh sửa câu trả lời và cung cấp một đoạn mã, nếu Matt không phiền.
Stan

1
Hmm đối với tôi, mảnh bản đồ không bị xóa. Tôi phải làm gì đó sai nhưng nếu tôi gọi getActivity (). GetSupportFragmentManager (). GetFragments (), đoạn vẫn còn sau khi gọi remove (f) .commit. Có ai có bất kỳ ý tưởng tại sao? (Tôi đã thay thế getFragManager bằng getSupportFragManager)
Daniel Wilson

10
commit ALLowingStateLoss sẽ tránh ngoại lệ IllegalStateException.
Héctor Júdez Sapena

22

Đây là câu trả lời của tôi:

1, Tạo bố cục xml như sau:

<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, trong lớp Fragment, thêm bản đồ google theo chương trình.

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();
    }
} 

2
mMapFragment.getMap();trả lại null. Bất cứ ý tưởng tại sao?
Anas Azeem

@AnasAzeem, tạo phân đoạn theo chương trình giải quyết chính xác vấn đề, bạn không cần phải lấy mMap cho giải pháp có thể trong trường hợp của bạn.
yesildal

@AnasAzeem bạn nên sử dụng get getAsAsync, nó sẽ trả về một thể hiện bản đồ chính xác sau khi khởi tạo (trong nền). Đây là cách làm việc "chính xác" với bản đồ google và không liên quan gì đến các mảnh vỡ
Ganesh Krishnan

10
  1. Như được đề cập bởi @Justin Breitfeller, giải pháp @Vidar Wahlberg là một bản hack có thể không hoạt động trong phiên bản Android trong tương lai.
  2. @Vidar Wahlberg cảm thấy bị hack vì giải pháp khác có thể "khiến bản đồ được tạo lại và vẽ lại, điều không phải lúc nào cũng mong muốn". Vẽ lại bản đồ có thể được ngăn chặn bằng cách duy trì đoạn bản đồ cũ, thay vì tạo một bản sao mới mỗi lần.
  3. Giải pháp @Matt không hoạt động với tôi (IllegalStateException)
  4. Như được trích dẫn bởi @Justin Breitfeller, "Bạn không thể thổi phồng bố cục thành một đoạn khi bố cục đó bao gồm một đoạn. Các đoạn lồng nhau chỉ được hỗ trợ khi được thêm vào một đoạn động."

Giải pháp của tôi:

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,                              Bundle savedInstanceState) {
    View view = inflater.inflate(R.layout.fragment_map_list, container, false);

    // init
    //mapFragment = (SupportMapFragment)getChildFragmentManager().findFragmentById(R.id.map);
    // don't recreate fragment everytime ensure last map location/state are maintain
    if (mapFragment == null) {
        mapFragment = SupportMapFragment.newInstance();
        mapFragment.getMapAsync(this);
    }
    FragmentTransaction transaction = getChildFragmentManager().beginTransaction();
    // R.id.map is a layout
    transaction.replace(R.id.map, mapFragment).commit();

    return view;
}

2
Cảm ơn @Desmond Giải pháp của bạn đã làm việc hoàn hảo cho tôi. Điều duy nhất bạn cần nhớ là KHÔNG tạo bản đồ trong bố cục. Tạo bản đồ trong giải pháp này được nhúng trong mã để thay đổi <Fragment android: name = "com.google.android.gms.maps.SupportMapFragment"> thành ví dụ <linearLayout id = "@ + id / map />
kosiara - Bartosz Kosarzycki

7

Khai báo đối tượng SupportMapFragment trên toàn cầu

    private SupportMapFragment mapFragment;

Trong phương thức onCreateView () đặt mã bên dưới

mapFragment = (SupportMapFragment) getChildFragmentManager()
            .findFragmentById(R.id.map);
 mapFragment.getMapAsync(this);

Trong onDestroyView () đặt mã bên dưới

@Override
public void onDestroyView() {
   super.onDestroyView();

    if (mapFragment != null)
        getFragmentManager().beginTransaction().remove(mapFragment).commit();
}

Trong tệp xml của bạn, đặt mã bên dưới

 <fragment
    android:id="@+id/map"
    android:name="com.abc.Driver.fragment.FragmentHome"
    class="com.google.android.gms.maps.SupportMapFragment"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    />

Mã trên đã giải quyết vấn đề của tôi và nó hoạt động tốt


3

Tôi muốn giới thiệu replace()chứ không phải attach()/detach() trong việc xử lý tab của bạn.

Hoặc, chuyển sang ViewPager. Đây là một dự án mẫu hiển thị một ViewPager, với các tab, lưu trữ 10 bản đồ.


Nhưng thay thế đưa ra lỗi outofmemry hơn những gì nên làm nếu chúng ta sử dụng cửa sổ tách ra hơn là vấn đề bản đồ xảy ra.
phát triển Vishal Android

3

Giải pháp khác:

if (view == null) {
    view = inflater.inflate(R.layout.nearbyplaces, container, false);
}

Đó là nó, nếu không null, bạn không cần phải xác định lại việc xóa nó khỏi cha mẹ là bước không cần thiết.


Đây là giải pháp tốt nhất cho trường hợp của tôi. Tôi đã gặp phải lỗi đó do sử dụng hai đoạn cho biểu đồ điều hướng của tôi và điều này đã khắc phục vấn đề của tôi.
Kennedy Kambo

Đây là giải pháp tốt nhất cho trường hợp của tôi. Tôi đã gặp phải lỗi đó do sử dụng hai đoạn cho biểu đồ điều hướng của tôi và điều này đã khắc phục vấn đề của tôi.
Kennedy Kambo

2

Tôi đã mất hàng giờ hôm nay để tìm lý do, may mắn là vấn đề này không phải do triển khai MapFragment, thật không may, điều này không hoạt động vì các đoạn lồng nhau chỉ được hỗ trợ thông qua thư viện hỗ trợ từ rev 11.

Việc triển khai của tôi có một hoạt động với thanh hành động (ở chế độ theo thẻ) với hai tab (không có chế độ xem), một có bản đồ và cái còn lại có một danh sách các mục. Tất nhiên, tôi đã khá ngây thơ khi sử dụng MapFragment bên trong các mảnh tab của mình, et voila ứng dụng bị sập mỗi khi tôi quay lại tab bản đồ.

(Vấn đề tương tự tôi cũng sẽ gặp phải trong trường hợp đoạn tab của tôi sẽ làm tăng bất kỳ bố cục nào có chứa bất kỳ đoạn nào khác).

Một tùy chọn là sử dụng MapView (thay vì MapFragment), với một số chi phí mặc dù (xem Tài liệu MapView là phần thay thế thả xuống trong layout.xml, một tùy chọn khác là sử dụng thư viện hỗ trợ từ phiên bản 11 nhưng sau đó sử dụng phương pháp lập trình do các đoạn lồng nhau không được hỗ trợ thông qua bố cục. Hoặc chỉ làm việc theo chương trình bằng cách phá hủy rõ ràng đoạn đó (như trong câu trả lời từ Matt / Vidar), btw: đạt được hiệu quả tương tự khi sử dụng MapView (tùy chọn 1).

Nhưng thực ra, tôi không muốn làm mất bản đồ mỗi khi tôi đi xa, nghĩa là tôi muốn giữ nó trong bộ nhớ và chỉ dọn dẹp khi hoạt động gần, vì vậy tôi quyết định chỉ ẩn / hiển thị bản đồ trong khi lập bảng, xem FragmentTransaction / ẩn


2

Đối với những người vẫn đang gặp phải vấn đề này, cách tốt nhất để đảm bảo bạn không gặp phải lỗi này với Map trong Tab là làm cho Fragment mở rộng SupportMapFragmentthay vì lồng SupportMapFragmentvào bên trong Fragment được sử dụng cho Tab.

Tôi vừa làm việc này bằng cách sử dụng ViewPagera FragmentPagerAdapter, với SupportMapFragment trong Tab thứ ba.

Đây là cấu trúc chung, lưu ý không cần ghi đè onCreateView()phương thức và không cần thổi phồng bất kỳ bố cục xml nào:

public class MapTabFragment extends SupportMapFragment 
                                    implements OnMapReadyCallback {

    private GoogleMap mMap;
    private Marker marker;


    public MapTabFragment() {
    }

    @Override
    public void onResume() {
        super.onResume();

        setUpMapIfNeeded();
    }

    private void setUpMapIfNeeded() {

        if (mMap == null) {

            getMapAsync(this);
        }
    }

    @Override
    public void onMapReady(GoogleMap googleMap) {

        mMap = googleMap;
        setUpMap();
    }

    private void setUpMap() {

        mMap.setMyLocationEnabled(true);
        mMap.setMapType(GoogleMap.MAP_TYPE_HYBRID);
        mMap.getUiSettings().setMapToolbarEnabled(false);


        mMap.setOnMapClickListener(new GoogleMap.OnMapClickListener() {

            @Override
            public void onMapClick(LatLng point) {

                //remove previously placed Marker
                if (marker != null) {
                    marker.remove();
                }

                //place marker where user just clicked
                marker = mMap.addMarker(new MarkerOptions().position(point).title("Marker")
                        .icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_MAGENTA)));

            }
        });

    }


}

Kết quả:

nhập mô tả hình ảnh ở đây

Dưới đây là mã lớp đầy đủ mà tôi đã sử dụng để kiểm tra, bao gồm Đoạn giữ chỗ được sử dụng cho hai Tab đầu tiên và Đoạn bản đồ được sử dụng cho Tab thứ ba:

public class MainActivity extends AppCompatActivity implements ActionBar.TabListener{


    SectionsPagerAdapter mSectionsPagerAdapter;

    ViewPager mViewPager;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        mSectionsPagerAdapter = new SectionsPagerAdapter(getSupportFragmentManager());

        // Set up the ViewPager with the sections adapter.
        mViewPager = (ViewPager) findViewById(R.id.pager);
        mViewPager.setAdapter(mSectionsPagerAdapter);

        final ActionBar actionBar = getSupportActionBar();
        actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);

        mViewPager.setOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() {
            @Override
            public void onPageSelected(int position) {
                actionBar.setSelectedNavigationItem(position);
            }
        });

        for (int i = 0; i < mSectionsPagerAdapter.getCount(); i++) {
            actionBar.addTab(actionBar.newTab().setText(mSectionsPagerAdapter.getPageTitle(i)).setTabListener(this));
        }

    }


    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.menu_main, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {

        int id = item.getItemId();

        if (id == R.id.action_settings) {
            return true;
        }

        return super.onOptionsItemSelected(item);
    }

    @Override
    public void onTabSelected(ActionBar.Tab tab, FragmentTransaction ft) {
        mViewPager.setCurrentItem(tab.getPosition());
    }

    @Override
    public void onTabUnselected(ActionBar.Tab tab, FragmentTransaction ft) {

    }

    @Override
    public void onTabReselected(ActionBar.Tab tab, FragmentTransaction ft) {

    }


    public class SectionsPagerAdapter extends FragmentPagerAdapter {

        public SectionsPagerAdapter(FragmentManager fm) {
            super(fm);
        }

        @Override
        public Fragment getItem(int position) {

            switch (position) {
                case 0:
                    return PlaceholderFragment.newInstance(position + 1);
                case 1:
                    return PlaceholderFragment.newInstance(position + 1);
                case 2:
                    return MapTabFragment.newInstance(position + 1);
            }

            return null;
        }

        @Override
        public int getCount() {
            // Show 3 total pages.
            return 3;
        }

        @Override
        public CharSequence getPageTitle(int position) {
            Locale l = Locale.getDefault();

            switch (position) {
                case 0:
                    return getString(R.string.title_section1).toUpperCase(l);
                case 1:
                    return getString(R.string.title_section2).toUpperCase(l);
                case 2:
                    return getString(R.string.title_section3).toUpperCase(l);
            }
            return null;
        }
    }


    public static class PlaceholderFragment extends Fragment {

        private static final String ARG_SECTION_NUMBER = "section_number";

        TextView text;

        public static PlaceholderFragment newInstance(int sectionNumber) {
            PlaceholderFragment fragment = new PlaceholderFragment();
            Bundle args = new Bundle();
            args.putInt(ARG_SECTION_NUMBER, sectionNumber);
            fragment.setArguments(args);
            return fragment;
        }

        public PlaceholderFragment() {
        }

        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container,
                                 Bundle savedInstanceState) {
            View rootView = inflater.inflate(R.layout.fragment_main, container, false);

            text = (TextView) rootView.findViewById(R.id.section_label);
            text.setText("placeholder");

            return rootView;
        }
    }

    public static class MapTabFragment extends SupportMapFragment implements
            OnMapReadyCallback {

        private static final String ARG_SECTION_NUMBER = "section_number";

        private GoogleMap mMap;
        private Marker marker;


        public static MapTabFragment newInstance(int sectionNumber) {
            MapTabFragment fragment = new MapTabFragment();
            Bundle args = new Bundle();
            args.putInt(ARG_SECTION_NUMBER, sectionNumber);
            fragment.setArguments(args);
            return fragment;
        }

        public MapTabFragment() {
        }

        @Override
        public void onResume() {
            super.onResume();

            Log.d("MyMap", "onResume");
            setUpMapIfNeeded();
        }

        private void setUpMapIfNeeded() {

            if (mMap == null) {

                Log.d("MyMap", "setUpMapIfNeeded");

                getMapAsync(this);
            }
        }

        @Override
        public void onMapReady(GoogleMap googleMap) {
            Log.d("MyMap", "onMapReady");
            mMap = googleMap;
            setUpMap();
        }

        private void setUpMap() {

            mMap.setMyLocationEnabled(true);
            mMap.setMapType(GoogleMap.MAP_TYPE_HYBRID);
            mMap.getUiSettings().setMapToolbarEnabled(false);


            mMap.setOnMapClickListener(new GoogleMap.OnMapClickListener() {

                @Override
                public void onMapClick(LatLng point) {

                    Log.d("MyMap", "MapClick");

                    //remove previously placed Marker
                    if (marker != null) {
                        marker.remove();
                    }

                    //place marker where user just clicked
                    marker = mMap.addMarker(new MarkerOptions().position(point).title("Marker")
                            .icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_MAGENTA)));

                    Log.d("MyMap", "MapClick After Add Marker");

                }
            });

        }
    }
}

2

Tôi tôn trọng tất cả các câu trả lời nhưng tôi đã tìm thấy giải pháp lót này: Nếu n là Số lượng tab thì:

 mViewPager.setOffscreenPageLimit(n);

Ví dụ: Trong trường hợp được đề cập:

 mViewPager.setOffscreenPageLimit(2);

Xem máy nhắn tin thực hiện một hàng đợi vì vậy, bạn không cần phải để nó loại bỏ đoạn đó. onCreateView chỉ được gọi một lần.


1

Bạn đang quay trở lại hoặc thổi phồng bố cục hai lần, chỉ cần kiểm tra xem nếu bạn chỉ thổi phồng một lần.



0

Bạn đã cố gắng tham chiếu MapFragmentlớp tùy chỉnh của mình trong tệp bố cục chưa?

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

    <fragment
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:id="@+id/mapFragment"
        android:name="com.nfc.demo.MapFragment"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />
</LinearLayout>

bạn có thể vui lòng gửi mã cho đoạn bản đồ tùy chỉnh com.nfc.demo.MapFragment
Mina Fawzy

Tôi không phải là tác giả của mã - Tôi chỉ sử dụng mã được đăng trong câu hỏi. Bạn phải hỏi hermann.
JJD

0

Nếu bạn sẽ chỉ sử dụng câu trả lời của Vidar Wahlberg, bạn sẽ gặp lỗi khi mở hoạt động khác (ví dụ) và quay lại bản đồ. Hoặc trong trường hợp của tôi, hãy mở hoạt động khác và sau đó từ hoạt động mới mở lại bản đồ (không sử dụng nút quay lại). Nhưng khi bạn kết hợp giải pháp Vidar Wahlberg và giải pháp Matt, bạn sẽ không có ngoại lệ.

bố trí

<com.example.ui.layout.MapWrapperLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:id="@+id/map_relative_layout">

    <RelativeLayout
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:id="@+id/root">

        <fragment xmlns:android="http://schemas.android.com/apk/res/android"
            android:id="@+id/map"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            class="com.google.android.gms.maps.SupportMapFragment" />
    </RelativeLayout>
</<com.example.ui.layout.MapWrapperLayout>

Miếng

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    setHasOptionsMenu(true);
    if (view != null) {
        ViewGroup parent = (ViewGroup) view.getParent();
        if (parent != null){
            parent.removeView(view);
        }
    }
    try {
        view = inflater.inflate(R.layout.map_view, null);
        if(view!=null){
            ViewGroup root = (ViewGroup) view.findViewById(R.id.root);
...

@Override
public void onDestroyView() {
    super.onDestroyView();
    Fragment fragment = this.getSherlockActivity().getSupportFragmentManager().findFragmentById(R.id.map);
    if (fragment != null)
        getFragmentManager().beginTransaction().remove(fragment).commit();
}

0

Tôi đã có điều này trong viewPager và sự cố là do bất kỳ đoạn nào phải có thẻ riêng, thẻ trùng lặp hoặc id cho cùng một đoạn không được phép.


0

Tôi nghĩ rằng có một số lỗi trong lib-Compat lib trước đây cho Fragment con. Tôi đã thử @Vidar Wahlberg và @ Matt là họ không làm việc cho tôi. Sau khi cập nhật thư viện appcompat, mã của tôi chạy hoàn hảo mà không cần nỗ lực thêm.


0

Điều cần lưu ý ở đây là ứng dụng của bạn sẽ gặp sự cố nghiêm trọng trong một trong hai trường hợp: -

1) Để sử dụng lại đoạn đó với Map một lần nữa, MapView Fragment phải được xóa khi đoạn của bạn hiển thị Maps đã được thay thế bằng đoạn khác trong cuộc gọi lại onDestroyView.

khác khi bạn cố gắng tăng cùng một đoạn hai lần ID trùng lặp, thẻ null hoặc id cha với một đoạn khác cho com.google.android.gms.maps.MapFragment sẽ xảy ra lỗi.

2) Thứ hai, bạn không được trộn các hoạt động của app.Fragment với android.support.v4.app.Fragment API hoạt động eg.do không sử dụng android.app.FragmentTransaction để loại bỏ v4.app.Fragment loại MapView Fragment. Trộn điều này một lần nữa sẽ dẫn đến sự cố từ phía mảnh.

Đây là đoạn mã mẫu để sử dụng MapView đúng cách

import android.content.Context;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Toast;

import com.google.android.gms.maps.CameraUpdateFactory;
import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.GoogleMap.OnMapClickListener;
import com.google.android.gms.maps.MapFragment;
import com.google.android.gms.maps.model.BitmapDescriptorFactory;
import com.google.android.gms.maps.model.CameraPosition;
import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.maps.model.MarkerOptions;
import com.serveroverload.yago.R;

/**
 * @author 663918
 *
 */
public class HomeFragment extends Fragment implements LocationListener {
    // Class to do operations on the Map
    GoogleMap googleMap;
    private LocationManager locationManager;

    public static Fragment newInstance() {
        return new HomeFragment();
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {
        View v = inflater.inflate(R.layout.home_fragment, container, false);
        Bundle bdl = getArguments();

        // setuping locatiomanager to perfrom location related operations
        locationManager = (LocationManager) getActivity().getSystemService(
                Context.LOCATION_SERVICE);

        // Requesting locationmanager for location updates
        locationManager.requestLocationUpdates(
                LocationManager.NETWORK_PROVIDER, 1, 1, this);

        // To get map from MapFragment from layout
        googleMap = ((MapFragment) getActivity().getFragmentManager()
                .findFragmentById(R.id.map)).getMap();

        // To change the map type to Satellite
        // googleMap.setMapType(GoogleMap.MAP_TYPE_SATELLITE);

        // To show our current location in the map with dot
        // googleMap.setMyLocationEnabled(true);

        // To listen action whenever we click on the map
        googleMap.setOnMapClickListener(new OnMapClickListener() {

            @Override
            public void onMapClick(LatLng latLng) {
                /*
                 * LatLng:Class will give us selected position lattigude and
                 * longitude values
                 */
                Toast.makeText(getActivity(), latLng.toString(),
                        Toast.LENGTH_LONG).show();
            }
        });

        changeMapMode(2);

        // googleMap.setSatellite(true);
        googleMap.setTrafficEnabled(true);
        googleMap.setBuildingsEnabled(true);
        googleMap.setMyLocationEnabled(true);

        return v;
    }

    private void doZoom() {
        if (googleMap != null) {
            googleMap.animateCamera(CameraUpdateFactory.newLatLngZoom(
                    new LatLng(18.520430, 73.856744), 17));
        }
    }

    private void changeMapMode(int mapMode) {

        if (googleMap != null) {
            switch (mapMode) {
            case 0:
                googleMap.setMapType(GoogleMap.MAP_TYPE_NONE);
                break;

            case 1:
                googleMap.setMapType(GoogleMap.MAP_TYPE_NORMAL);
                break;

            case 2:
                googleMap.setMapType(GoogleMap.MAP_TYPE_SATELLITE);
                break;

            case 3:
                googleMap.setMapType(GoogleMap.MAP_TYPE_TERRAIN);
                break;

            case 4:
                googleMap.setMapType(GoogleMap.MAP_TYPE_HYBRID);
                break;

            default:
                break;
            }
        }
    }

    private void createMarker(double latitude, double longitude) {
        // double latitude = 17.385044;
        // double longitude = 78.486671;

        // lets place some 10 random markers
        for (int i = 0; i < 10; i++) {
            // random latitude and logitude
            double[] randomLocation = createRandLocation(latitude, longitude);

            // Adding a marker
            MarkerOptions marker = new MarkerOptions().position(
                    new LatLng(randomLocation[0], randomLocation[1])).title(
                    "Hello Maps " + i);

            Log.e("Random", "> " + randomLocation[0] + ", " + randomLocation[1]);

            // changing marker color
            if (i == 0)
                marker.icon(BitmapDescriptorFactory
                        .defaultMarker(BitmapDescriptorFactory.HUE_AZURE));
            if (i == 1)
                marker.icon(BitmapDescriptorFactory
                        .defaultMarker(BitmapDescriptorFactory.HUE_BLUE));
            if (i == 2)
                marker.icon(BitmapDescriptorFactory
                        .defaultMarker(BitmapDescriptorFactory.HUE_CYAN));
            if (i == 3)
                marker.icon(BitmapDescriptorFactory
                        .defaultMarker(BitmapDescriptorFactory.HUE_GREEN));
            if (i == 4)
                marker.icon(BitmapDescriptorFactory
                        .defaultMarker(BitmapDescriptorFactory.HUE_MAGENTA));
            if (i == 5)
                marker.icon(BitmapDescriptorFactory
                        .defaultMarker(BitmapDescriptorFactory.HUE_ORANGE));
            if (i == 6)
                marker.icon(BitmapDescriptorFactory
                        .defaultMarker(BitmapDescriptorFactory.HUE_RED));
            if (i == 7)
                marker.icon(BitmapDescriptorFactory
                        .defaultMarker(BitmapDescriptorFactory.HUE_ROSE));
            if (i == 8)
                marker.icon(BitmapDescriptorFactory
                        .defaultMarker(BitmapDescriptorFactory.HUE_VIOLET));
            if (i == 9)
                marker.icon(BitmapDescriptorFactory
                        .defaultMarker(BitmapDescriptorFactory.HUE_YELLOW));

            googleMap.addMarker(marker);

            // Move the camera to last position with a zoom level
            if (i == 9) {
                CameraPosition cameraPosition = new CameraPosition.Builder()
                        .target(new LatLng(randomLocation[0], randomLocation[1]))
                        .zoom(15).build();

                googleMap.animateCamera(CameraUpdateFactory
                        .newCameraPosition(cameraPosition));
            }
        }

    }

    /*
     * creating random postion around a location for testing purpose only
     */
    private double[] createRandLocation(double latitude, double longitude) {

        return new double[] { latitude + ((Math.random() - 0.5) / 500),
                longitude + ((Math.random() - 0.5) / 500),
                150 + ((Math.random() - 0.5) * 10) };
    }

    @Override
    public void onLocationChanged(Location location) {

        if (null != googleMap) {
            // To get lattitude value from location object
            double latti = location.getLatitude();
            // To get longitude value from location object
            double longi = location.getLongitude();

            // To hold lattitude and longitude values
            LatLng position = new LatLng(latti, longi);

            createMarker(latti, longi);

            // Creating object to pass our current location to the map
            MarkerOptions markerOptions = new MarkerOptions();
            // To store current location in the markeroptions object
            markerOptions.position(position);

            // Zooming to our current location with zoom level 17.0f
            googleMap.animateCamera(CameraUpdateFactory.newLatLngZoom(position,
                    17f));

            // adding markeroptions class object to the map to show our current
            // location in the map with help of default marker
            googleMap.addMarker(markerOptions);
        }

    }

    @Override
    public void onStatusChanged(String provider, int status, Bundle extras) {
        // TODO Auto-generated method stub

    }

    @Override
    public void onProviderEnabled(String provider) {
        // TODO Auto-generated method stub

    }

    @Override
    public void onProviderDisabled(String provider) {
        // TODO Auto-generated method stub

    }

    @Override
    public void onDestroyView() {
        // TODO Auto-generated method stub
        super.onDestroyView();

        locationManager.removeUpdates(this);

        android.app.Fragment fragment = getActivity().getFragmentManager()
                .findFragmentById(R.id.map);
        if (null != fragment) {
            android.app.FragmentTransaction ft = getActivity()
                    .getFragmentManager().beginTransaction();
            ft.remove(fragment);
            ft.commit();
        }
    }

}

XML

 <fragment
        android:id="@+id/map"
        android:name="com.google.android.gms.maps.MapFragment"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
       />

Kết quả trông như thế này: -nhập mô tả hình ảnh ở đây

Hy vọng nó sẽ giúp được ai đó.


0

Trong giải pháp này, bạn không cần phải lấy biến tĩnh;

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

Tôi đến bữa tiệc hơi muộn nhưng Non trong số những câu trả lời này đã giúp tôi trong trường hợp của mình. Tôi đã sử dụng bản đồ Google dưới dạng SupportMapFragmentPlaceAutocompleteFragment cả trong đoạn của tôi. Vì tất cả các câu trả lời đều chỉ ra thực tế rằng vấn đề là với SupportMapFragment là bản đồ được tạo lại và vẽ lại. Nhưng sau khi đào tìm ra vấn đề của tôi thực sự là PlaceAutocompleteFragment

Vì vậy, đây là giải pháp hiệu quả cho những ai đang gặp phải vấn đề này vì SupportMapFragmentSupportMapFragment

 //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);

    }

Và trong onDestroyView, xóa SupportMapFragment và 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

Hãy thử đặt id (android: id = "@ + id / maps_dialog") cho bố cục cha mẹ mapView của bạn. Làm việc cho tôi.


0

Bây giờ bất cứ ai đến đây đều gặp phải loại lỗi này khi mở một Dialoghoặc khác Fragmentvới Google Địa điểm AutocompleteSupportFragment, hãy thử một lớp lót này (Tôi không biết cách này an toàn nhưng nó hoạt động với tôi):

autocompleteFragment.getFragmentManager().beginTransaction().remove(autocompleteFragment).commit();

trước khi bạn loại bỏ / phá hủy mảnh vỡ của bạn.


-1
<?xml version="1.0" encoding="utf-8"?>

  <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
  android:layout_width="match_parent"
   android:layout_height="match_parent" >


<com.google.android.gms.maps.MapView
    android:id="@+id/mapview"
    android:layout_width="100dip"
    android:layout_height="100dip"
    android:layout_alignParentTop="true"
    android:layout_alignRight="@+id/textView1"
    android:layout_marginRight="15dp" >
</com.google.android.gms.maps.MapView>

Tại sao bạn không chèn bản đồ bằng đối tượng MapView thay vì MapFragment? Tôi không chắc chắn nếu có bất kỳ giới hạn nào trong MapView, mặc dù tôi thấy nó hữu ích.


Xin lỗi tôi đã biết rằng đó là phiên bản API Google Maps không dùng nữa
Ankur Gautam
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.