在MapFragment和ListFragment之间切换

3

我正在创建一个应用程序,其中我想在我的CustomMapFragmentListFragment之间切换。如果我启动应用程序并调用replaceFragment

private void replaceFragment(final Fragment fragment) {
    final FragmentManager fragmentManager = mActivity.getFragmentManager();
    fragmentManager.beginTransaction()
            .replace(R.id.main_content_frame, fragment)
            .commit();
}

通过使用replaceFragment(new CustomMapFragment()),地图看起来应该是正常的。 CustomMapFragment是一个碎片,在其中我用本机的MapFragment替换了一个FrameLayout,以使其与代码分离。
如果我再次调用替换方法,例如在按钮单击或其他事件中,使用不同的Fragment(例如ListFragment),则FrameLayout将被替换为此,一切正常。
现在,如果我尝试再次使用CustomMapFragment进行替换,与一开始完全相同的调用,则会加载地图,但缺少我在CustomMapFragment中完成的每个Marker和每个设置。 CustomMapFragment:
public class CustomMapFragment extends BaseFragment {

    private static final String LOG_TAG = PosMapFragment.class.getSimpleName();
    private MapFragment mMapFragment;
    private GoogleMap   mMap;
    private ImageLoader mImageLoader;

    private Context     mContext;

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

        mContext = getActivity();

        final RequestQueue reqQueue = Volley.newRequestQueue(mContext);
        mImageLoader = new ImageLoader(reqQueue, new BitmapLruCache(mContext));
    }

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

    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);

        mMapFragment = MapFragment.newInstance();
        replaceFragment(mMapFragment);
    }

    private void postMapInitialisation() {
        new View(getActivity()).post(new Runnable() {
            @Override
            public void run() {
                addTestMarker(0, 0, "http://www.jimis-cyberstore.com/store/media/gp_batman_tshirts.jpg");
                addTestMarker(10, 10, "http://img.netzwelt.de/software/icons/2012/8842/android-sdk.png");
                addTestMarker(50, 50, "http://fs02.androidpit.info/ali/x84/4053084-1374511678988-80x80.png");
                addTestMarker(5, 0, "http://im.wk.io/images/77e3e40/kitkat-chromium-ubernimmt-in-android.jpeg");
                addTestMarker(0, 10, "http://www.mchme.de/cms/kategorien/18_Software/dateien/fb_logo_80.jpg");
                addTestMarker(15, 5, "http://navigator.ptvgroup.com/uploads/pics/PTV_Navigator_Android_Windows2_80x80px_01.png");
            }
        });
    }

    @Override
    public void onResume() {
        super.onResume();
        setUpMapIfNeeded();
        postMapInitialisation();
        EventBusProvider.getInstance().register(this);
    }

    private void replaceFragment(final Fragment fragment) {
        final FragmentManager fragmentManager = getFragmentManager();
        fragmentManager.beginTransaction()
                .replace(R.id.maps, fragment)
                .commit();
    }

    private void setUpMapIfNeeded() {
        if (mMap == null) {
            mMap = mMapFragment.getMap();
            if (mMap != null) {
                mMap.setMyLocationEnabled(true);
                mMap.setInfoWindowAdapter(this);
                mMap.setOnInfoWindowClickListener(this);
            }
        }
    }

    private void addTestMarker(final double lat, final double lng, String url){
        if(mMap != null){
            final NetworkImageMarker networkImageMarker = new NetworkImageMarker(mContext, url);
            final Marker marker = mMap.addMarker(networkImageMarker.getMarkerOptions(lat, lng, mImageLoader));
            networkImageMarker.setMarker(marker);
            networkImageMarker.setReloadListener(new OnReloadListener() {
                @Override
                public void reAddNetworkImageMarker(Bitmap bitmap) {
                    mMap.addMarker(networkImageMarker.getMarkerOptions(lat, lng, bitmap));
                }
            });
        }
    }

    @Subscribe
    public void onLocationChanged(final LocationChangedEvent event) {
        centerMap(event.mLocation);
    }

    private void centerMap(Location location){
        double latitude = location.getLatitude();
        double longitude = location.getLongitude();
        LatLng latLng = new LatLng(latitude, longitude);
        centerMapAtLocation(latLng);
    }

    private void centerMapAtLocation(LatLng location) {
        mMap.moveCamera(CameraUpdateFactory.newLatLng(location));
        mMap.animateCamera(CameraUpdateFactory.zoomTo(14));
    }
}

主要布局只是一个FrameLayout,在不同的Fragment中进行更换。我还尝试了只加载一个Fragment,其中CustomMapFragment和ListFragment同时加载,使用两个FrameLayout叠放在一起,但最终效果相同。 看来问题出在MapFragment上(而不是SupportMapFragment)。
- 在开头加载MapFragment = MapFragment看起来完美 - MapFragment -> ListFragment -> MapFragment = MapFragment为空地图 - ListFragment -> MapFragment = MapFragment为空地图 - MapFragment -> MapFragment = MapFragment为空地图

setUpMapIfNeeded()中调用postMapInitialisation()会有什么区别吗? - JJD
setUpMapIfNeeded() 只在 onResume() 中调用,而 postMapInitialisation() 总是在 setUpMapIfNeeded() 之后调用。所以我猜这不会有什么区别。 - Informatic0re
请尝试将 postMapInitialisation() 移动到您的 if 条件中。我怀疑 map 仍然为 null - JJD
我尝试过了,但是没有任何变化 - 看起来这个地图和第一个加载的地图不同。它也没有启用像我的位置或指南针之类的设置。在调试时,我看到他添加了标记并设置了地图。我认为有两个地图重叠在一起,原因不明。 - Informatic0re
请检查以下两点:(1) 在 addTestMarker() 函数中添加 else 分支,以处理 mMap == null 的情况。(2) 请在您的 Activity 中检查 CustomMapFragment 实例是否相同。 - JJD
第二次调用后,地图始终为 null,即使调用了 fragment.getMap()。如果我调用 replaceFragment,我总是使用 new Fragment()。这适用于除了带有 MapFragment 的片段之外的所有片段。 - Informatic0re
1个回答

4

如果你想替换另一个碎片(fragment)中的碎片,应该在replace方法中使用getChildFragmentManager()而不是getFragmentManager()。

private void replaceFragment(final Fragment fragment) {
    final FragmentManager fragmentManager = getChildFragmentManager();
    fragmentManager.beginTransaction()
            .replace(R.id.maps, fragment)
            .commit();
}

很遗憾,getChildFragmentManager()仅支持api级别>=17,因此您可能需要使用android-support-v4库。


我遇到了一个问题,就是列表的页脚在切换时消失了。使用getChildFragmentManager解决了我的问题。 - Victor Pinto

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接