I want to show a MapView in a fragment. The map is shown as what I expected, but it seems it is only shown as a picture. I cannot drag to move camera or spread/pinch to zoom. I also tried to use SupportMapFragment in my fragment, but got the same result.
I have a NavigationView in my Activity. I do not think there's conflict on the touch event of NavigationView and MapView.
Anyone met this before?
fragment
public class CustomizedMapFragment extends Fragment implements OnMapReadyCallback{
MapView mapView;
GoogleMap googleMap;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_map, container, false);
mapView = (MapView) rootView.findViewById(R.id.mapView);
mapView.onCreate(savedInstanceState);
mapView.getMapAsync(this);
return rootView;
}
#Override
public void onMapReady(GoogleMap googleMap) {
this.googleMap = googleMap;
this.googleMap.getUiSettings().setZoomControlsEnabled(true);
this.googleMap.getUiSettings().setZoomGesturesEnabled(true);
}
#Override
public void onResume() {
super.onResume();
mapView.onResume();
}
#Override
public void onPause() {
super.onPause();
mapView.onPause();
}
#Override
public void onDestroy() {
super.onDestroy();
mapView.onDestroy();
}
#Override
public void onLowMemory() {
super.onLowMemory();
mapView.onLowMemory();
}
}
layout
<?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:layout_margin="16dp"
android:id="#+id/mapView"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</RelativeLayout>
Try to use this UiSettings.setScrollGesturesEnabled(boolean), by using this you can scroll (pan) around the map by dragging the map with their finger.
Another way is configure these options when the map is created via XML attributes.
<fragment xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:map="http://schemas.android.com/apk/res-auto"
android:name="com.google.android.gms.maps.SupportMapFragment"
android:id="#+id/map"
android:layout_width="match_parent"
android:layout_height="match_parent"
map:cameraBearing="112.5"
map:cameraTargetLat="-33.796923"
map:cameraTargetLng="150.922433"
map:cameraTilt="30"
map:cameraZoom="13"
map:mapType="normal"
map:uiCompass="false"
map:uiRotateGestures="true"
map:uiScrollGestures="false"
map:uiTiltGestures="true"
map:uiZoomControls="false"
map:uiZoomGestures="true"/>
But in order to use these custom attributes within your XML layout file, you must first add the following namespace declaration.
xmlns:map="http://schemas.android.com/apk/res-auto"
For more information, check this documentation.
Related
I get the following error when I try to leave fragment which contains map (on back button press).
ERROR: mapInflater->Binary XML file line #7: Error inflating class fragment
Bellow is onCreate() method of fragment where the map is placed. And also there is a xml code of layout.
#Override
public void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
apiRequestManager = ApiRequestManager.getInstance();
fragmentHandler = FragmentHandlerActivityMain.getInstance(getActivity());
session = new SessionManager(App.getInstance().getApplicationContext());
((AppCompatActivity) getActivity()).getSupportActionBar().setTitle(getString(R.string.maps_fragment_toolbar_name));
Handler mainHandler = new Handler();
Runnable myRunnable = new Runnable() {
#Override
public void run() {
try {
SupportMapFragment maps = (SupportMapFragment) getChildFragmentManager()
.findFragmentById(R.id.mapView);
if (maps != null)
maps.getMapAsync(MapsFragment.this);
} catch (Exception ex) {
LogUtil.getInstance().add(LogUtil.ERROR,
TAG, "onCreateMaps", ex);
}
}
};
mainHandler.post(myRunnable);
}
Log is pointing on this layout on fragment (line 7).
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app1="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".salesman.fragments.MapsFragment">
<fragment
android:id="#+id/mapView"
android:name="com.google.android.gms.maps.SupportMapFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clickable="true"/>
</FrameLayout>
You are trying to getChildFragmentManager() instade of getSupportFragmentManager().
Need to change In Java File :
1). You need to implements OnMapReadyCallback in Your Fragment.
2). Get SupportMapFragment from View.
SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager()
.findFragmentById(R.id.map);
mapFragment.getMapAsync(this);
3). Overrid onMapReady(GoogleMap googlMap) Method.
#Override
public void onMapReady(GoogleMap googleMap) {
// Add a marker in Sydney, Australia,
LatLng sydney = new LatLng(-33.852, 151.211);
googleMap.addMarker(new MarkerOptions().position(sydney).title("Marker in Sydney"));
// and move the map's camera to the same location.
googleMap.moveCamera(CameraUpdateFactory.newLatLng(sydney));
}
In XML File :-
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app1="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".salesman.fragments.MapsFragment">
<fragment xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/map"
android:name="com.google.android.gms.maps.SupportMapFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</FrameLayout>
Please check the updated answer as per below comment:
Now try to set MapView insted of fragment because if you use fragment inside fragment it creates lot of issues.
Need to change in JAVA Code : // Initialize GoogleMap myMap; MapView mMapView;
// OnCreateView Method MapsInitializer.initialize(this.getActivity()); mMapView = (MapView) rootView.findViewById(R.id.map); mMapView.onCreate(savedInstanceState); mMapView.getMapAsync(this);
#Override public void onPause() { super.onPause(); mMapView.onPause(); }
#Override public void onPause() { super.onPause(); mMapView.onPause(); }
#Overridepublic void onResume() { super.onResume(); mMapView.onResume(); }
Need to change in XML File :
<com.google.android.gms.maps.MapView android:id="#+id/map" android:layout_width="match_parent" android:layout_height="match_parent" />
I need a search toolbar on Google Map.
I display the map with the use of MapActivity.
The way I did is via the create project wizard, when you a create a new project, you can choose from basic activity, empty activity, map activity.
I selected MapActivity.
In XML file I had only this:
<resources>
<string name="google_maps_key" templateMergeStrategy="preserve"
translatable="false">AIzaSyCx3iR5fkeWr2LUf6JBHwGLEEkeghL3snk
</string>
</resources>
So what is the way to insert that search toolbar on the map?
Then how to add that search tool bar. If I add a layout then an error it is shown.
The way I would do it is the following:
I would have an activity which has a fragment that contain the map inside.
Inside the activity I would have a method that display the fragment with the map:
public void showMap() {
MapLocationFragment locationFragment = MapLocationFragment.newInstance();
getSupportFragmentManager().beginTransaction()
.replace(R.id.fragment_container, locationFragment)
.addToBackStack(null)
.commit();
}
activity xml:
<?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">
<include
android:id="#+id/app_bar_include"
layout="#layout/app_bar_layout_device" />
<FrameLayout
android:id="#+id/fragment_container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginTop="?attr/actionBarSize" />
</RelativeLayout>
Now, inside the MapLocationFragment you need to have something like that:
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.maps_layout, container, false);
return view;
}
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
initializeMapIfNeeded();
}
private void initializeMapIfNeeded() {
if (googleMap == null) {
loadMapAsync();
}
}
private void loadMapAsync() {
((SupportMapFragment) getChildFragmentManager().findFragmentById(R.id.location_map)).getMapAsync(getOnMapReadyCallback());
}
public OnMapReadyCallback getOnMapReadyCallback() {
return new OnMapReadyCallback() {
#Override
public void onMapReady(GoogleMap map) {
googleMap = map;
if (googleMap == null) {
return;
}
googleMap.setIndoorEnabled(true);
googleMap.getUiSettings().setMyLocationButtonEnabled(true);
googleMap.setOnMyLocationButtonClickListener(getMapMpOnMyLocationClickListener());
googleMap.setLocationSource(getNewLocationSource());
googleMap.setOnCameraChangeListener(getCameraChangeListener());
//do other stuff too
}
};
}
xml:
<android.support.design.widget.CoordinatorLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto">
<fragment
android:id="#+id/location_map"
class="com.google.android.gms.maps.SupportMapFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
<android.support.design.widget.FloatingActionButton
android:id="#+id/fab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="16dp"
android:clickable="true"
android:src="#android:drawable/ic_menu_set_as"
app:layout_anchorGravity="bottom|right|end"
android:layout_gravity="bottom|end"/>
</android.support.design.widget.CoordinatorLayout>
For more details look at this project:
Sunshine app
You can try it.
public class MapsActivity extends FragementActivity implements OnMapReadyCallback,LocationListener in here, Put the AppCompatActivity instead of the FragementActivity.
I having trouble implementing Google Map in Fragment.
This is my the part of my fragment class:
public class FragmentStoreFinderMap extends Fragment implements OnMapReadyCallback {
// Google Map
private GoogleMap googleMap;
private int i;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
googleMap = ((SupportMapFragment)getActivity().getSupportFragmentManager().findFragmentById(
R.id.map)).getMapAsync(this);
I am getting an error in getMapAsync(this). I tells Incompatible type.
it says:
required: com.google.android.gms.map.GoogleMap
found: void
BTW here is my xml:
<?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 class="com.google.android.gms.maps.SupportMapFragment"
android:id="#+id/map"
android:name="com.google.android.gms.maps.SupportMapFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</LinearLayout>
In your XML layout you should do like this
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.google.android.gms.maps.MapView
android:id="#+id/map"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</FrameLayout>
inside your fragment implement this
private MapView mapView;
private GoogleMap googleMap;
override onCreateView if there is no onCreateView just like the code below
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.your_layout, container, false);
}
override onViewCreated() inside that
onViewCreated() put this
mapView = (MapView) view.findViewById(R.id.map);
mapView.onCreate(savedInstanceState);
mapView.onResume();
mapView.getMapAsync(this);//when you already implement OnMapReadyCallback in your fragment
when you already implement OnMapReadyCallback in your fragment put this/code like this
#Override
public void onMapReady(GoogleMap map) {
googleMap = map;
}
hope this helps you.
After a few overheats in my head, thanks to this post and https://stackoverflow.com/a/34732804/3925554, I would say that currently there are two ways of adding a MapFragment to your app:
<fragment xmlns:android="http://schemas.android.com/apk/res/android"
class="com.google.android.gms.maps.SupportMapFragment"
android:id="#+id/map"
android:name="com.google.android.gms.maps.SupportMapFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
By this way, you have to use a standard fragment and implement this inside. Actually you are inserting a fragment into another:
#Override
public void onViewCreated(View view, #Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
SupportMapFragment supportMapFragment = (SupportMapFragment) getChildFragmentManager().findFragmentById(R.id.map);
supportMapFragment.getMapAsync(this);
}
The other way would be extending the real SupportMapFragment and implement it in this manner without the need of an xml:
#Override
public void onViewCreated(View view, #Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
getMapAsync(this);
}
And they work without having to set a layout in onCreateView neither call mapView.onCreate(savedInstanceState); and mapView.onResume(); manually inside onViewCreated(), what is not recommended anyway.
Hope it helps!
SupportMapFragment mMapFragment = SupportMapFragment.newInstance();
FragmentTransaction fragmentTransaction =
getChildFragmentManager().beginTransaction();
fragmentTransaction.add(R.id.flMap, mMapFragment);
fragmentTransaction.commit();
mMapFragment.getMapAsync(this);
Your code is returning this error because getMapAsync() does not return anything. If you look at the documentation for this function:
public void getMapAsync (OnMapReadyCallback callback)
Sets a callback object which will be triggered when the GoogleMap
instance is ready to be used.
Note that:
This method must be called from the main thread. The callback will be
executed in the main thread. In the case where Google Play services is
not installed on the user's device, the callback will not be triggered
until the user installs it. In the rare case where the GoogleMap is
destroyed immediately after creation, the callback is not triggered.
The GoogleMap object provided by the callback is non-null.
OnMapReadyCallback is an interface that needs implemented and passed to through this function. Nothing is currently assigned to your googleMap variable you should instead set its value in this block of code which implements OnMapReadyCallback
#Override
public void onMapReady(GoogleMap googleMap) {
this.googleMap = googleMap;
}
This code should be in your Fragment somewhere. Since your Fragment already implements this interface you do pass it in as this.
I need to add a map dynamically into the app to my MainActivity, otherwise I somehow suffer on memory leaks. Adding the map basically works, but I can't add markers. They just don't appear. That's how I add the map:
activity_main.xml which is used by the MainActivity
<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<!-- Placeholder for all fragments -->
<RelativeLayout
android:id="#+id/fragment_container"
android:layout_width="match_parent"
android:layout_height="match_parent" >
</RelativeLayout>
<!-- Slider menu -->
<LinearLayout
android:id="#+id/list_container"
android:layout_width="240dp"
android:layout_height="match_parent"
android:layout_gravity="start"
android:background="#fff"
android:orientation="vertical" >
<!-- more code -->
</LinearLayout>
</android.support.v4.widget.DrawerLayout>
fragment_map.xml
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#id/fragment_container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center" >
<fragment
xmlns:map="http://schemas.android.com/apk/res-auto"
android:id="#+id/fragment_googlemap"
android:layout_width="match_parent"
android:layout_height="match_parent"
class="com.androidmapsextensions.SupportMapFragment"
map:cameraTargetLat="48.21167860510698"
map:cameraTargetLng="16.365892895859423"
map:cameraZoom="11"
map:uiCompass="true"
map:uiRotateGestures="true"
map:uiScrollGestures="true"
map:uiTiltGestures="true"
map:uiZoomControls="true"
map:uiZoomGestures="true" />
</FrameLayout>
MapFragment.java
public class MapFragment extends com.androidmapsextensions.SupportMapFragment
{
private static final String TAG = MapFragment.class.getSimpleName();
private OnFragmentLoadedCompleteListener onFragmentLoadedCompleteListener;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle args)
{
super.onCreateView(inflater, container, args);
Logger.log(TAG, "onCreateView()", LogController.isLoggingEnabled(), Log.DEBUG);
return inflater.inflate(R.layout.fragment_map, container, false);
}
#Override
public void onActivityCreated(Bundle savedInstanceState)
{
super.onActivityCreated(savedInstanceState);
Logger.log(TAG, "onActivityCreated()", LogController.isLoggingEnabled(), Log.DEBUG);
onFragmentLoadedCompleteListener.onFragmentComplete();
}
#Override
public void onAttach(Activity activity)
{
super.onAttach(activity);
Logger.log(TAG, "onAttach()", LogController.isLoggingEnabled(), Log.DEBUG);
onFragmentLoadedCompleteListener = (OnFragmentLoadedCompleteListener)activity;
}
}
Important parts of MainActivity.java
#Override
public void onFragmentComplete()
{
googleMap = ((SupportMapFragment)getSupportFragmentManager().findFragmentByTag("mapFragment")).getExtendedMap();
}
private void initMapFragment()
{
if (googleMap != null)
{
googleMap.clear();
googleMap = null;
}
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new MapFragment(), "mapFragment").commit();
}
OnFragmentLoadedCompleteListener.java
public interface OnFragmentLoadedCompleteListener
{
public void onFragmentComplete();
}
onFragmentComplete() is executed, googleMap is not null and shown. But I can't draw markers on it. They just don't appear.
But when I don't dynamically add the map and embed it into the activity_main.xml within the RelativeLayout like this
<RelativeLayout
android:id="#+id/fragment_container"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<fragment
xmlns:map="http://schemas.android.com/apk/res-auto"
android:id="#+id/fragment_googlemap"
android:layout_width="match_parent"
android:layout_height="match_parent"
class="com.androidmapsextensions.SupportMapFragment"
map:cameraTargetLat="48.21167860510698"
map:cameraTargetLng="16.365892895859423"
map:cameraZoom="11"
map:uiCompass="true"
map:uiRotateGestures="true"
map:uiScrollGestures="true"
map:uiTiltGestures="true"
map:uiZoomControls="true"
map:uiZoomGestures="true" />
</RelativeLayout>
and fetch the map like this without the listener, I can draw markers, that means they appear.
googleMap = ((SupportMapFragment)getSupportFragmentManager().findFragmentById(R.id.fragment_googlemap)).getExtendedMap();
That means drawing markers on the map only works when I directly embed the map into the xml of the MainActivity instead of added it dynamically as fragment. What's going on here. Where is the error?
As is often the case I found the solution on my own.
I have to keep a reference to my MapFragment I use to replace:
mapFragment = new MapFragment();
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, mapFragment).commit();
In onFragmentComplete() I have to invoke getChildFragmentManager() on this reference to obtain the "correct" GoogleMap.
googleMap = ((SupportMapFragment)mapFragment.getChildFragmentManager().findFragmentById(R.id.fragment_googlemap)).getExtendedMap();
This time it can be found by id as well (didn't work before), and drawing markers on this map works now.
I'm using sliding menu for Android here is the link, when I slide on rendered map fragment, the sliding menu goes blank.
Here is my map fragment code.
public class BasicMapActivity extends SherlockFragment {
private MapView mMapView;
private GoogleMap mMap;
#Override
public View onCreateView(LayoutInflater inflater,
ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.basic_demo, null);
// view.setBackgroundColor(0x00000000);
mMapView = (MapView) view.findViewById(R.id.map);
container.requestTransparentRegion(mMapView);
mMapView.onCreate(savedInstanceState);
return view;
}
}
Here is my home activity where in i render map.
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_home_frame);
getSupportFragmentManager()
.beginTransaction()
.replace(R.id.home_screen, new BasicMapActivity())
.commit();
getSlidingMenu().setSecondaryMenu(
getLayoutInflater().inflate(R.layout.resq_events_frame, null));
getSupportFragmentManager()
.beginTransaction()
.replace(R.id.resq_events_screen, new EventsFragment())
.commit();
// set the Behind View
setBehindContentView(R.layout.activity_settings_frame);
getSupportFragmentManager()
.beginTransaction()
.replace(R.id.settings_screen, new SettingsFragment())
.commit();
// customize the SlidingMenu
getSlidingMenu().setTouchModeAbove(SlidingMenu.TOUCHMODE_FULLSCREEN);
}
My XML file looks like this
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/home_screen"
android:layout_width="match_parent"
android:layout_height="match_parent">
</FrameLayout>
How to overcome by this issue?
Here how the image looks.
The issue is due to GoogleMap, you have to add this map:zOrderOnTop="true" to your XML map layout, like
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent" >
<fragment
android:name="com.google.android.gms.maps.SupportMapFragment"
xmlns:map="http://schemas.android.com/apk/res-auto"
android:id="#+id/map"
android:layout_width="match_parent"
android:layout_height="match_parent"
map:zOrderOnTop="true" />
</LinearLayout>