i try to create a map in a fragment in a swipe view, but with this code i have a error in logcat, this is the code:
public class Mapa extends Fragment {
private static final double MARKER_LATITUDE = 42.027325;
private static final double MARKER_LONGITUDE = -8.640842;
GoogleMap map;
private FragmentActivity myContext;
public Mapa() {
}
/**
* Returns a new instance of this fragment for the given section
* number.
*/
public static Mapa newInstance() {
Mapa fragment = new Mapa();
return fragment;
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View android = inflater.inflate(R.layout.mapa, container, false);
final LatLng position = new LatLng(MARKER_LATITUDE, MARKER_LONGITUDE);
// camera position
map.setOnCameraChangeListener(new GoogleMap.OnCameraChangeListener()
{
#Override
public void onCameraChange(CameraPosition arg0)
{
CameraUpdate cu = CameraUpdateFactory.newLatLngZoom(position, 17);
map.animateCamera(cu);
map.setOnCameraChangeListener(null);
map.setMapType(GoogleMap.MAP_TYPE_HYBRID);
}
});
return android;
}
#Override
public void onAttach(Activity activity) {
myContext=(FragmentActivity) activity;
super.onAttach(activity);
}
#Override
public void onDestroyView() {
super.onDestroyView();
Fragment f = getFragmentManager().findFragmentById(R.id.mapFragment);
if (f != null)
getFragmentManager().beginTransaction().remove(f).commit();
}
}
and this is the logcat error:
java.lang.NullPointerException: Attempt to invoke virtual method 'void com.google.android.gms.maps.GoogleMap.setOnCameraChangeListener(com.google.android.gms.maps.GoogleMap$OnCameraChangeListener)' on a null object reference
at greetrack.estg.ipvc.greentrack.Mapa.onCreateView(Mapa.java:49)
its my first application using maps, maybe somethings is wrong
You havent setup map, its null. So the null reference.
Map = ((MapFragment) getFragmentManager().findFragmentById(
R.id.mapView)).getMap();
is one way, or potentially following googles recommendation. Here is a maps fragment xml.
The xml file i put in isn't showing https://developers.google.com/maps/documentation/android/start#get_an_android_certificate_and_the_google_maps_api_key here is the linkk to it.
Add the following code in MainActivity.java.
package com.example.mapdemo;
import android.app.Activity;
import android.os.Bundle;
public class MainActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
}
Related
I tried to use callback to communicate between my fragments but it seems that infowindowfragment does not recognize my mapFragment as its parentfragment, is there something I can do to work or have another way to do this?
Mapfragment (parentFragment):
public class MapFragment extends Fragment implements MapView, OnMapReadyCallback, //GoogleMap.InfoWindowAdapter,
GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener
,InfoWindowFragment.OnChildFragmentInteractionListener{
...
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
mapInfoWindowFragment =
(MapInfoWindowFragment) getChildFragmentManager().findFragmentById(R.id.map);
mapInfoWindowFragment.getMapAsync(this);
}
...
#Override
public void onMapReady(GoogleMap googleMap) {
map = googleMap;
setOnMakerClick(map);
moveCameraToLastKnowLocation();
}
...
public void setOnMakerClick(final GoogleMap googleMap){
googleMap.setOnMarkerClickListener(new GoogleMap.OnMarkerClickListener() {
#Override
public boolean onMarkerClick(Marker marker) {
NearDriver nearDriver = markers.get(marker);
LatLng position = new LatLng(nearDriver.getLatitude()+0.007, nearDriver.getLongitude());
googleMap.moveCamera(CameraUpdateFactory.newLatLngZoom(position, 15));
//marker.showInfoWindow();
final int offsetX = (int) getResources().getDimension(R.dimen.marker_offset_x);
final int offsetY = (int) getResources().getDimension(R.dimen.marker_offset_y);
final InfoWindow.MarkerSpecification markerSpec =
new InfoWindow.MarkerSpecification(offsetX, offsetY);
InfoWindowFragment infoWindowFragment = new InfoWindowFragment();
final InfoWindow infoWindow = new InfoWindow(marker, markerSpec, infoWindowFragment);
mapInfoWindowFragment.infoWindowManager().toggle(infoWindow, true);
infoWindowFragment.render(nearDriver);
return true;
}
});
}
...
#Override
public void messageFromChildToParent(Place place) {
Log.d("d", "MapFragment - Place: " + place.getName());
setOnMakerClick(map);
}
InfoWindowFragment ("ChildFragment"):
public interface OnChildFragmentInteractionListener {
void messageFromChildToParent(Place place);
}
#Override
public void onAttach(Context context) {
super.onAttach(context);
// check if parent Fragment implements listener
if (getParentFragment() instanceof OnChildFragmentInteractionListener) {
mParentListener = (OnChildFragmentInteractionListener) getParentFragment();
} else {
throw new RuntimeException("The parent fragment must implement OnChildFragmentInteractionListener");
}
}
Logcat:
06-13 00:53:57.427 18791-18791/com.rsm.yuri.projecttaxilivre E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.rsm.yuri.projecttaxilivre, PID: 18791
java.lang.RuntimeException: The parent fragment must implement OnChildFragmentInteractionListener
at com.rsm.yuri.projecttaxilivre.map.InteractiveInfoWindow.InfoWindowFragment.onAttach(InfoWindowFragment.java:175)
I solved this problem by changing the way to access the mapfragment:
#Override
public void onAttach(Context context) {
super.onAttach(context);
if (context instanceof MainActivity) {
MainActivity mainActivity = (MainActivity) context;
MapFragment parentFragment = mainActivity.getMapFragment();
if (parentFragment != null) {
mParentListener = (OnChildFragmentInteractionListener) parentFragment;
} else {
throw new RuntimeException("The parent fragment must implement OnChildFragmentInteractionListener");
}
}
}
I need to Add a Mark to a Android Google Map (Fragment) from a MainActivity
This is my code;
class Map extends android.app.Fragment implements OnMapReadyCallback
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
return inflater.inflate(R.layout.activity_mapa, container,false);
}
#Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
MapFragment fragment = (MapFragment)getChildFragmentManager().findFragmentById(R.id.map);
fragment.getMapAsync(this);
}
#Override
public void onMapReady(GoogleMap googleMap) {
LatLng marker = new LatLng(19.33978502, -99.19086277);
googleMap.moveCamera(CameraUpdateFactory.newLatLngZoom(marker, 15));
googleMap.addMarker(new MarkerOptions().title("Marca de Prueba 1").position(marker));
}
}
And i want to add a mark from here:
All this because i want to interact with my map from my main Activity where i have some buttons and EditText
MainActivity
public class MainActivityextends AppCompatActivity
implements NavigationView.OnNavigationItemSelectedListener
{
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_side_bar);
}
FragmentManager fm = getFragmentManager();
fm.beginTransaction().replace(R.id.content_frame, new Mapa()).commit();
}
Here is how it looks, already has a mark, but insted of calling it from the map activity i need to set it from the MainActivity
You just need to define a public method in the Fragment that can be called from the Activity:
class Mapa extends android.app.Fragment implements OnMapReadyCallback
GoogleMap mMap;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
return inflater.inflate(R.layout.activity_mapa, container,false);
}
#Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
MapFragment fragment = (MapFragment)getChildFragmentManager().findFragmentById(R.id.map);
fragment.getMapAsync(this);
}
#Override
public void onMapReady(GoogleMap googleMap) {
mMap = googleMap;
}
//Added public method to be called from the Activity
public void placeMarker(String title, double lat, double lon) {
if (mMap != null) {
LatLng marker = new LatLng(lat, lon);
mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(marker, 15));
mMap.addMarker(new MarkerOptions().title(title).position(marker));
}
}
}
Then, in the Activity, keep a reference to the Fragment so that you can call the placeMarker() method:
public class MainActivity extends AppCompatActivity
implements NavigationView.OnNavigationItemSelectedListener {
private Mapa mMapFragment;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_side_bar);
}
mMapFragment = new Mapa();
FragmentManager fm = getFragmentManager();
fm.beginTransaction().replace(R.id.content_frame, mMapFragment).commit();
}
private void placeMarkerInMap(String title, double lat, double lon) {
if (mMapFragment != null) {
mMapFragment.placeMarker(title, lat, lon);
}
}
}
Then you can call the placeMarkerInMap() method in your Activity when the user fills out the EditText and clicks the button.
Note that if you try to call this method before the onMapReady() callback executes, there will not be a valid GoogleMap reference to use to place the Marker.
If you need to place a Marker on initial launch from the Activity, you'll need to use arguments in the FragmentTransaction. See here for more details.
How to get access from main activity to fragment? I want to add marker in fragment class with location from recycledview. Object with location data is in ClubBean. I obtained this by interface ClubAdapter.OnClubClickListener:
#Override
public void onClicked (ClubBean club) {
ClubBean bean = club;
Log.d("Name: ", bean.getClubName());
}
Main Activity:
public class MapsActivity extends FragmentActivity implements LoadAllClubsInterface, ClubAdapter.OnClubClickListener {
private DrawerLayout drawerLayout;
private RecyclerView clubRecycler;
private RecyclerView.LayoutManager clubLayoutManager;
private ArrayList<ClubBean> clubList = new ArrayList<ClubBean>();
private RecyclerView.Adapter clubAdapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_maps);
FragmentManager fm = getSupportFragmentManager();
fm.beginTransaction().replace(R.id.content_frame, new MyMapFragment()).commit();
new LoadAllClubs(this).execute(); //load list in background from database
drawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
clubRecycler = (RecyclerView) findViewById(R.id.recycler_view);
clubRecycler.setHasFixedSize(true);
clubLayoutManager = new LinearLayoutManager(this);
clubRecycler.setLayoutManager(clubLayoutManager);
}
#Override
public void finishDataLoad(ArrayList<HashMap<String, String>> clubs) {
Iterator<HashMap<String, String>> iterator = clubs.iterator();
Map<String, String> map = new HashMap<String, String>();
while (iterator.hasNext()){
map = iterator.next();
clubList.add(new ClubBean(map.get("name"),map.get("localization"), map.get("score")));
}
//pass the class that implements your listener as a parameter.
clubAdapter = new ClubAdapter(clubList, this, this);
clubRecycler.setAdapter(clubAdapter);
}
#Override
public void onClicked (ClubBean club) {
ClubBean bean = club;
Log.d("Name: ", bean.getClubName());
}
}
My MapFragment Class:
public class MyMapFragment extends Fragment implements OnMapReadyCallback{
GoogleMap mGoogleMap;
MapView mMapView;
View mView;
public MyMapFragment(){
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
mView = inflater.inflate(R.layout.map_fragment, container, false);
return mView;
}
#Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
mMapView = (MapView) mView.findViewById(R.id.map);
if (mMapView != null){
mMapView.onCreate(null);
mMapView.onResume();
mMapView.getMapAsync(this);
}
}
#Override
public void onMapReady(GoogleMap googleMap) {
MapsInitializer.initialize(getActivity().getApplicationContext());
mGoogleMap = googleMap;
LatLng triCity = new LatLng(54.4158773,18.6337789);
mGoogleMap.addMarker(new MarkerOptions().position(triCity).title("Trojmiasto"));
mGoogleMap.moveCamera(CameraUpdateFactory.newLatLngZoom(triCity, 11));
}
}
The convenient way of communication between Activity and Fragment is via Interface. Here is example code based on your problem:
Step 1: Define an interface like this:
public interface IFragmentController{
void passDataToFragmentMethod(String someStringValue);
}
Step 2:Implement this Interface into your fragment. Then you will get passDataToFragmentMethod(String someStringValue) method in your fragment.
public class MyMapFragment extends Fragment implements IFragmentController{
#Override
void passDataToFragmentMethod(String someStringValue){
// So your logic code here using passed value
}
}
Step 3: In your Activity just get instance of your fragment and call passDataToFragmentMethod method in this way:
Fragment mapFragment=new MyMapFragment();
and
#Override
public void onClicked (ClubBean club) {
ClubBean bean = club;
Log.d("Name: ", bean.getClubName());
mapFragment.passDataToFragmentMethod(bean.getClubName());
}
Hope this will help you to solve your problem :)
The host activity can deliver messages to a fragment by capturing the Fragment instance with findFragmentById(), then directly call the fragment's public methods.
https://developer.android.com/training/basics/fragments/communicating.html
Just define a method in MyMapFragment like addMarkers, then call it from activity.
You can do something like this
public class MapsActivity extends FragmentActivity implements LoadAllClubsInterface, ClubAdapter.OnClubClickListener {
MyMapFragment mMyFragment;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_maps);
mMyFragment=new MyMapFragment();
FragmentManager fm = getSupportFragmentManager();
fm.beginTransaction().replace(R.id.content_frame,mMyFragment).commit();
}
private void addMarkers(){
//defined this method in Mapfragment
mMyFragment.addMarkers();
}
if u have list then
For(ClubBean obj:ClubList)
{
// latitude and longitude
double latitude =obj.getLatValue();
double longitude = obj.getLngValue();
// create marker
MarkerOptions marker = new MarkerOptions().position(new LatLng(latitude, longitude)).title("Hello Maps ");
// adding marker
googleMap.addMarker(marker);
}
I am using actionbarsherlock to implement a set of tabs. One of the tabs is a fragment containing a MapView. My onCreateView is as follows:
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
View view = inflater.inflate(R.layout.mapview, container, false);
mMapView = (MapView) view.findViewById(R.id.mapv);
mMapView.onCreate(savedInstanceState);
mMapView.onResume();
try
{
MapsInitializer.initialize(getActivity());
}
catch (GooglePlayServicesNotAvailableException e)
{
e.printStackTrace();
}
googleMap = mMapView.getMap();
googleMap.getUiSettings().setMyLocationButtonEnabled(true);
googleMap.moveCamera(CameraUpdateFactory.newLatLngZoom(PARIS, 10));
googleMap.addMarker(new MarkerOptions().position(PARIS).title("Paris").snippet("Great city"));
return view;
}
As you can see, the map is originally displayed zoomed in on Paris, which has a Marker on it. Everything is working fine so far. I see the map and can manually drag and zoom the map. If I then press the button on the side of my phone to cause it to pause, then unlock the phone to resume, I can still drag and zoom. BUT if I switch to another tab, then come back to the map tab, I see the map as I left it, but it no longer responds to drag/zoom. It appears frozen. But no errors are being displayed in my log and I can still flip between tabs.
Without any log errors, I don't know how to track down the problem.
EDIT: I'm using Maps v2
EDIT: I've just found a similar sounding situation here. It may well be the answer, but I don't know quite where to place the code from the suggested solution.
EDIT: Just in case the critical code was not in my snippet, here's the whole thing...
package com.mycompany.myapp;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.ViewGroup;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentTransaction;
import com.actionbarsherlock.app.ActionBar.Tab;
import com.actionbarsherlock.app.ActionBar.TabListener;
import com.google.android.gms.common.GooglePlayServicesNotAvailableException;
import com.google.android.gms.maps.CameraUpdateFactory;
import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.MapView;
import com.google.android.gms.maps.MapsInitializer;
import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.maps.model.MarkerOptions;
import android.view.View;
public class TestMapFragment extends Fragment implements TabListener
{
private Fragment mFragment;
private MapView mMapView;
private GoogleMap googleMap;
private static final LatLng PARIS = new LatLng(48.874,2.347);
#Override
public void onActivityCreated(Bundle savedInstanceState)
{
super.onActivityCreated(savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
View view = inflater.inflate(R.layout.mapview, container, false);
mMapView = (MapView) view.findViewById(R.id.mapv);
mMapView.onCreate(savedInstanceState);
mMapView.onResume();
try
{
MapsInitializer.initialize(getActivity());
}
catch (GooglePlayServicesNotAvailableException e)
{
e.printStackTrace();
}
googleMap = mMapView.getMap();
googleMap.getUiSettings().setMyLocationButtonEnabled(true);
googleMap.moveCamera(CameraUpdateFactory.newLatLngZoom(PARIS, 10));
googleMap.addMarker(new MarkerOptions().position(PARIS).title("Paris").snippet("Great city"));
return view;
}
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setRetainInstance(true);
}
#Override
public void onTabSelected(Tab tab, FragmentTransaction ft)
{
mFragment = new TestMapFragment();
ft.add(android.R.id.content, mFragment);
ft.attach(mFragment);
}
#Override
public void onTabUnselected(Tab tab, FragmentTransaction ft) {
// TODO Auto-generated method stub
}
#Override
public void onTabReselected(Tab tab, FragmentTransaction ft) {
// TODO Auto-generated method stub
}
/*
* Using a mapview in a fragment requires you to 'route'
* the lifecycle events of the fragment to the mapview
*/
#Override
public void onResume()
{
super.onResume();
if (mMapView != null)
{
mMapView.onResume();
}
}
#Override
public void onPause()
{
super.onPause();
if (mMapView != null)
{
mMapView.onPause();
}
}
#Override
public void onDestroy()
{
super.onDestroy();
if (mMapView != null)
{
mMapView.onDestroy();
}
}
#Override
public void onSaveInstanceState(Bundle outState)
{
super.onSaveInstanceState(outState);
if (mMapView != null)
{
mMapView.onSaveInstanceState(outState);
}
}
#Override
public void onLowMemory()
{
super.onLowMemory();
if (mMapView != null)
{
mMapView.onLowMemory();
}
}
}
This added line container.removeAllViewsInLayout() seems to have done the trick.
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
container.removeAllViewsInLayout();
View view = inflater.inflate(R.layout.mapview, container, false);
i also had the same problem
i have done something like this
Fragment activity which will hold the fragments
Map_main_screen.java
public class Map_main_screen extends FragmentActivity {
private static final String[] CONTENT = new String[] { "TAB one",
"Second tab GOOGLE MAP", };
#Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.map_new);
FragmentPagerAdapter adapter = new GoogleMusicAdapter(
getSupportFragmentManager());
ViewPager pager = (ViewPager) findViewById(R.id.pager);
pager.setAdapter(adapter);
TabPageIndicator indicator = (TabPageIndicator)findViewById(R.id.indicator);
indicator.setViewPager(pager);
==========================new_class_GoogleMusicAdapter============================
class GoogleMusicAdapter extends FragmentPagerAdapter {
public GoogleMusicAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int position) {
return Map_google_TestFragment.newInstance(CONTENT[position
% CONTENT.length]);
}
#Override
public CharSequence getPageTitle(int position) {
return CONTENT[position % CONTENT.length].toUpperCase();
}
#Override
public int getCount() {
return CONTENT.length;
}
}
// =================adapter ends here===============================
}
Map_google_TestFragment.java
public final class Map_google_TestFragment extends Fragment {
private static final String KEY_CONTENT = "TestFragment:Content";
Typeface tf;
public static Map_google_TestFragment newInstance(String content) {
Map_google_TestFragment fragment = new Map_google_TestFragment();
StringBuilder builder = new StringBuilder();
for (int i = 0; i < 1; i++) {
builder.append(content).append(" ");
}
builder.deleteCharAt(builder.length() - 1);
fragment.mContent = builder.toString();
return fragment;
}
private String mContent = "???";
private int[] mICONS = { 1 };
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if ((savedInstanceState != null)
&& savedInstanceState.containsKey(KEY_CONTENT)) {
mContent = savedInstanceState.getString(KEY_CONTENT);
}
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
LayoutInflater vi = (LayoutInflater) getActivity().getSystemService(
Context.LAYOUT_INFLATER_SERVICE);
View v;
if (mContent.toString().equals("TAB one")) {
v = vi.inflate(R.layout.YOUR_SECOND_LAYOUT, null);
//***************************************
// function related to your first fragment
//***************************************
} else {
//***************************************
// inflate your Google map layout here
// function related to your Second fragment
//***************************************
View view = inflater.inflate(R.layout.mapview, container, false); //INFLATE GOOGLE MAP LAYOUT
mMapView = (MapView) view.findViewById(R.id.mapv);
mMapView.onCreate(savedInstanceState);
mMapView.onResume();
try
{
MapsInitializer.initialize(getActivity());
}
catch (GooglePlayServicesNotAvailableException e)
{
e.printStackTrace();
}
googleMap = mMapView.getMap();
googleMap.getUiSettings().setMyLocationButtonEnabled(true);
googleMap.moveCamera(CameraUpdateFactory.newLatLngZoom(PARIS, 10));
googleMap.addMarker(new MarkerOptions().position(PARIS).title("Paris").snippet("Great city"));
return view;
}
#Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putString(KEY_CONTENT, mContent);
}
}
Have you tried using mMapView.displayZoomControls(true) right after mMapView = (MapView) view.findViewById(R.id.mapv)?
I'm trying to add a MapFragment to my current Fragment. The use of nested fragments is restricted to FragmentTransactions, you can't use the xml tag in your layout.
Also, I want it to be added to the main Fragment when the user presses a button. So, I'm creating the MapFragment programmatically with getInstance() when the user presses that button and adding it to the proper place. It is shown correctly, so far so good.
The problem is that after attaching the MapFragment I need to get a reference to GoogleMap to place a Marker, but the getMap() method returns null (as the fragment's onCreateView() hasn't been called yet).
I looked at the demo example code and I found the solution they use is initializing the MapFragment in onCreate() and getting the reference to GoogleMap in onResume(), after onCreateView() has been called.
I need to get the reference to GoogleMap right after the MapFragment initialization, because I want the users to be able to show or hide the map with a button. I know a possible solution would be to create the Map at the start as said above and just set it's visibility gone, but I want the map to be off by default so it doesn't take the user's bandwidth if they don't explicitly asked for it.
I tried with the MapsInitializer, but doesn't work either. I'm kind of stuck. Any ideas?
Here is my testing code so far:
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"));
}
}
}
}
Thanks
The good AnderWebs gave me an answer in Google+ but he is too laz.... emm busy to write it here again, so here is the short version:
Extend the MapFragment class and override the onCreateView() method. After this method is done we can get a non-null reference to que GoogleMap object.
This is my particular 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)));
}
}
Now in the previous Fragment class I do
mMapFragment = MiniMapFragment.newInstance(new LatLng(37.4005502611301, -5.98233461380005));
Maybe it's not perfect yet, because the screen blinks when showing the map. But not sure if the problem is because of this or something else.
Thanks, found this very helpful. Am posting my slightly modified solution, as it was cleaner for me to tell the parent Fragment when the map was ready. This method also works with a saveInstanceState / restoreInstanceState cycle.
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();
}
}
To use as a nested Fragment:-
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();
}
...
}
Hope it helps someone.
Here's my solution to this, I took inspiration from the code previously posted and cleaned it up. I also added the static methods with and without the GoogleMapOptions parameters.
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;
}
The usage pattern is as follows:
public class MyMapActivity implements OnGoogleMapFragmentListener {
...
#Override
public void onMapReady(GoogleMap map) {
mUIGoogleMap = map;
...
}
...
private GoogleMap mUIGoogleMap;
}
No need to cutomize SupportMapFragment you can do this directly by using following piece of code,
FragmentManager fm = getSupportFragmentManager(); // getChildFragmentManager inside fragments.
CameraPosition cp = new CameraPosition.Builder()
.target(initialLatLng) // your initial co-ordinates here. like, LatLng initialLatLng
.zoom(zoom_level)
.build();
SupportMapFragment mapFragment = SupportMapFragment.newInstance(new GoogleMapOptions().camera(cp));
fm.beginTransaction().replace(R.id.rl_map, mapFragment).commit();
Add this piece of code for layout
<RelativeLayout
android:id="#+id/rl_map"
android:layout_width="fill_parent"
android:layout_height="fill_parent" />
This will load GoogleMap at particular Location directly i.e, initialLatLng.