48 votes

Initialiser MapFragment par programme avec Maps API v2

J'essaye d'ajouter un MapFragment à mon Fragment. L'utilisation d'imbrication des fragments est limité à FragmentTransactions, vous ne pouvez pas utiliser la balise xml dans votre mise en page. Aussi, je veux qu'il soit ajouté à la principale Fragment lorsque l'utilisateur appuie sur un bouton. Donc, je suis de la création de la MapFragment par programme avec l' getInstance() lorsque l'utilisateur appuie sur le bouton et en l'ajoutant à la bonne place. Il est indiqué correctement, c'est très bien.

Le problème est que, après fixation de la MapFragment j'ai besoin d'obtenir une référence à l' GoogleMap pour placer un Marqueur, mais l' getMap() méthode renvoie la valeur null (comme le fragment de la onCreateView() n'a pas été appelée encore).

J'ai regardé la démo exemple de code et j'ai trouvé la solution qu'ils utilisent est l'initialisation de la MapFragment en onCreate() et l'obtention de la référence à GoogleMap en onResume(), après onCreateView() a été appelé.

J'ai besoin de pour obtenir la référence à GoogleMap juste après la MapFragment d'initialisation, parce que je veux que les utilisateurs soient en mesure d'afficher ou de masquer la carte avec un bouton. Je connais une solution possible serait de créer de la Carte au début comme dit plus haut et il suffit de le mettre visibilité du parti, mais je tiens à la carte sera désactivée par défaut afin de ne pas prendre de l'utilisateur de la bande passante si elles ne sont pas explicitement demandé.

J'ai essayé avec l' MapsInitializer, mais cela ne fonctionne pas. Je suis un peu coincé. Des idées? Voici mon code de test pour l'instant:

public class ParadaInfoFragment extends BaseDBFragment {
// BaseDBFragment is just a SherlockFragment with custom utility methods.

private static final String MAP_FRAGMENT_TAG = "map";
private GoogleMap mMap;
private SupportMapFragment mMapFragment;
private TextView mToggleMapa;
private boolean isMapVisible = false;

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    View v = inflater.inflate(R.layout.fragment_parada_info, container, false);
    mToggleMapa = (TextView) v.findViewById(R.id.parada_info_map_button);
    return v;
}

@Override
public void onStart() {
    super.onStart();
    mToggleMapa.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            if (!isMapVisible) {
                openMap();
            } else {
                closeMap();
            }
            isMapVisible = !isMapVisible;
        }
    });
}

private void openMap() {
    // Creates initial configuration for the map
    GoogleMapOptions options = new GoogleMapOptions().camera(CameraPosition.fromLatLngZoom(new LatLng(37.4005502611301, -5.98233461380005), 16))
            .compassEnabled(false).mapType(GoogleMap.MAP_TYPE_NORMAL).rotateGesturesEnabled(false).scrollGesturesEnabled(false).tiltGesturesEnabled(false)
            .zoomControlsEnabled(false).zoomGesturesEnabled(false);

    // Modified from the sample code:
    // It isn't possible to set a fragment's id programmatically so we set a
    // tag instead and search for it using that.
    mMapFragment = (SupportMapFragment) getChildFragmentManager().findFragmentByTag(MAP_FRAGMENT_TAG);

    // We only create a fragment if it doesn't already exist.
    if (mMapFragment == null) {
        // To programmatically add the map, we first create a
        // SupportMapFragment.
        mMapFragment = SupportMapFragment.newInstance(options);
        // Then we add it using a FragmentTransaction.
        FragmentTransaction fragmentTransaction = getChildFragmentManager().beginTransaction();
        fragmentTransaction.add(R.id.parada_info_map_container, mMapFragment, MAP_FRAGMENT_TAG);
        fragmentTransaction.commit();
    }
    // We can't be guaranteed that the map is available because Google Play
    // services might not be available.
    setUpMapIfNeeded(); //XXX Here, getMap() returns null so  the Marker can't be added
    // The map is shown with the previous options.
}

private void closeMap() {
    FragmentTransaction fragmentTransaction = getChildFragmentManager().beginTransaction();
    fragmentTransaction.remove(mMapFragment);
    fragmentTransaction.commit();
}

private void setUpMapIfNeeded() {
    // Do a null check to confirm that we have not already instantiated the
    // map.
    if (mMap == null) {
        // Try to obtain the map from the SupportMapFragment.
        mMap = mMapFragment.getMap();
        // Check if we were successful in obtaining the map.
        if (mMap != null) {
            mMap.addMarker(new MarkerOptions().position(new LatLng(37.4005502611301, -5.98233461380005)).title("Marker"));
        }
    }
}
}

Merci

53voto

Sloy Points 1400

La bonne AnderWebs m'a donné une réponse dans Google+ , mais il est trop laz.... emm occupé à écrire ici encore, donc, voici la version courte: Étendre la MapFragment de classe et de remplacer les onCreateView() la méthode. Après cette méthode est faite, nous pouvons obtenir une valeur non nulle référence à québec GoogleMap objet.

C'est ma solution:

public class MiniMapFragment extends SupportMapFragment {

private LatLng mPosFija;


public MiniMapFragment() {
    super();

}

public static MiniMapFragment newInstance(LatLng posicion){
    MiniMapFragment frag = new MiniMapFragment();
    frag.mPosFija = posicion;
    return frag;
}

@Override
public View onCreateView(LayoutInflater arg0, ViewGroup arg1, Bundle arg2) {
    View v = super.onCreateView(arg0, arg1, arg2);
    initMap();
    return v;
}

private void initMap(){
    UiSettings settings = getMap().getUiSettings();
    settings.setAllGesturesEnabled(false);
    settings.setMyLocationButtonEnabled(false);

    getMap().moveCamera(CameraUpdateFactory.newLatLngZoom(mPosFija,16));
    getMap().addMarker(new MarkerOptions().position(mPosFija).icon(BitmapDescriptorFactory.fromResource(R.drawable.marker)));
}
}

Maintenant, dans le Fragment précédent de la classe, je ne mMapFragment = MiniMapFragment.newInstance(new LatLng(37.4005502611301, -5.98233461380005));

C'est peut-être pas encore parfait, parce que l'écran clignote lorsque l'affichage de la carte. Mais vous ne savez pas si le problème est à cause de cela ou d'autre chose.

25voto

Ryan Points 1188

Merci, j'ai trouvé cela très utile. Je poste ma solution légèrement modifiée, car il était plus facile pour moi de dire au fragment parent que la carte était prête. Cette méthode fonctionne également avec un cycle saveInstanceState / restoreInstanceState.

 public class CustomMapFragment extends SupportMapFragment {

    private static final String LOG_TAG = "CustomMapFragment";

    public CustomMapFragment() {
        super();

    }

    public static CustomMapFragment newInstance() {
        CustomMapFragment fragment = new CustomMapFragment();
        return fragment;
    }

    @Override
    public View onCreateView(LayoutInflater arg0, ViewGroup arg1, Bundle arg2) {
        View v = super.onCreateView(arg0, arg1, arg2);
        Fragment fragment = getParentFragment();
        if (fragment != null && fragment instanceof OnMapReadyListener) {
            ((OnMapReadyListener) fragment).onMapReady();
        }
        return v;
    }



    /**
     * Listener interface to tell when the map is ready
     */
    public static interface OnMapReadyListener {

        void onMapReady();
    }
}
 

Pour utiliser comme fragment imbriqué: -

 public class ParentFragment extends Fragment implements OnMapReadyListener {

    ...

    mMapFragment = CustomMapFragment.newInstance();
    getChildFragmentManager().beginTransaction().replace(R.id.mapContainer, mMapFragment).commit();

    @Override
    public void onMapReady() {
        mMap = mMapFragment.getMap();
    }
    ...
}
 

J'espère que ça aide quelqu'un.

14voto

Matteo Giaccone Points 131

Voici ma solution à cela, je me suis inspiré du code précédemment posté et l'ai nettoyé. J'ai également ajouté les méthodes statiques avec et sans les paramètres GoogleMapOptions.

 public class GoogleMapFragment extends SupportMapFragment {

    private static final String SUPPORT_MAP_BUNDLE_KEY = "MapOptions";

    public static interface OnGoogleMapFragmentListener {
        void onMapReady(GoogleMap map);
    }

    public static GoogleMapFragment newInstance() {
        return new GoogleMapFragment();
    }

    public static GoogleMapFragment newInstance(GoogleMapOptions options) {
        Bundle arguments = new Bundle();
        arguments.putParcelable(SUPPORT_MAP_BUNDLE_KEY, options);

        GoogleMapFragment fragment = new GoogleMapFragment();
        fragment.setArguments(arguments);
        return fragment;
    }

    @Override
    public void onAttach(Activity activity) {
        super.onAttach(activity);
        try {
            mCallback = (OnGoogleMapFragmentListener) getActivity();
        } catch (ClassCastException e) {
            throw new ClassCastException(getActivity().getClass().getName() + " must implement OnGoogleMapFragmentListener");
        }
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View view = super.onCreateView(inflater, container, savedInstanceState);
        if (mCallback != null) {
            mCallback.onMapReady(getMap());
        }
        return view;
    }

    private OnGoogleMapFragmentListener mCallback;
}
 

Le modèle d'utilisation est la suivante:

 public class MyMapActivity implements OnGoogleMapFragmentListener {

    ...

    @Override
    public void onMapReady(GoogleMap map) {
        mUIGoogleMap = map;

        ...

    }

    ...

    private GoogleMap mUIGoogleMap;
}
 

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X