I would like to put an Google Map in a fragment, but please be noted that I want to put it inside the onActivityCreated, and the fragment class just need to extend fragment class only.
And my final layout will be:
This is a fragment contains a text, map and button.
~~~~~~~~~~~~~~~
Textview.....
Map.....
Button....
~~~~~~~~~~~~~~~
Also, the map need include my current location.
May I know how to do that? with java and xml please :)
In your Fragment layout put a MapView widget:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:map="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<!-- My TextView -->
<com.google.android.gms.maps.MapView android:id="#+id/my_map"
android:layout_width="match_parent"
android:layout_height="match_parent"
map:uiZoomControls="false"
map:uiCompass="false"
map:uiRotateGestures="false"
map:uiScrollGestures="true"
map:uiTiltGestures="false"
map:uiZoomGestures="true"
android:visibility="visible"/>
<!-- My Button and eventually others widgets -->
</RelativeLayout>
Your fragment will inflate your custom layout with the MapView and the others widgets you need in . Here a pseudo code about how to setup the MapView.
public class MyCustomFragmentWithMap extends Fragment {
private MapView mMapView = null;
private GoogleMap mMyMap = null;
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
try {
MapsInitializer.initialize(getActivity());
} catch (GooglePlayServicesNotAvailableException err) {
Log.e(TAG, err.getMessage(), err);
}
mMapView = (MapView)getView().findViewById(R.id.my_map);
mMapView.onCreate(savedInstanceState);
mMyMap = mMapView.getMap();
mMyMap.setMyLocationEnabled(true);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.my_custom_fragment_with_map, container, false);
/* All the widgets setup as usual ... */
return view;
}
#Override
public void onResume() {
super.onResume();
if (mMapView != null)
mMapView.onResume();
}
#Override
public void onPause() {
if (mMapView != null)
mMapView.onPause();
super.onPause();
}
#Override
public void onDestroy() {
if (mMapView != null)
mMapView.onDestroy();
super.onDestroy();
}
#Override
public void onLowMemory() {
super.onLowMemory();
if (mMapView != null)
mMapView.onLowMemory();
}
#Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
if (mMapView != null)
mMapView.onSaveInstanceState(outState);
}
I'm assuming that you already know how to setup the Google Maps Android API v2 (obtaining the api key, setting permissions in manifest and all the boring stuffs :-P).
Related
I have a Google Maps mapView in a ScrollView. it works fine, except when Scrolling I get some ugly black backgrounds along the bottom and top.
Here's a video of the issue:
https://www.youtube.com/watch?v=wLla7nS6Ehc&feature=youtu.be
To fix this, I wrapped the Map in a FrameLayout and made it bigger than the actual container, this fixes the issue, except now I can't see the Google watermark anymore. I tried using a bottom padding, but with the padding the black pattern shows up again, but this time only at the bottom.
Is it okay to put a TextView in the FrameLayout with the font and style of the Google Maps watermark as a work around? Am I violating the TOS if I do this?
This is the xml for my fix:
<FrameLayout
android:id="#+id/map_view_container"
android:layout_width="match_parent"
android:layout_height="200dp"
android:layout_below="#+id/location"
android:layout_centerHorizontal="true"
android:layout_marginTop="#dimen/full_margin"
android:background="#color/transparent">
<com.google.android.gms.maps.MapView
android:id="#+id/map_view"
android:layout_width="match_parent"
android:layout_height="400dp"
android:layout_gravity="center"
android:background="#color/off_white"
map:mapType="normal" />
<View
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/transparent" />
</FrameLayout>
EDIT: Fragment code:
public class MapFragment extends Fragment
implements View.OnClickListener,
com.google.android.gms.maps.OnMapReadyCallback {
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_business_home, container, false);
final Bundle mapViewSavedInstanceState = savedInstanceState != null ? savedInstanceState.getBundle("mapViewSaveState") : null;
initializeViewComponents(rootView, mapViewSavedInstanceState);
return rootView;
}
private void initializeViewComponents(View rootView, Bundle savedInstanceState) {
scrollView = (ScrollView) rootView.findViewById(R.id.scroll_view);
mapView = (MapView) rootView.findViewById(R.id.map_view);
mapView.onCreate(savedInstanceState);
mapView.getMapAsync(this);
}
#Override
public void onMapReady(GoogleMap googleMap) {
MapsInitializer.initialize(this.getActivity());
this.map = googleMap;
// Gets to GoogleMap from the MapView and does initialization stuff
map.getUiSettings().setMyLocationButtonEnabled(true);
map.getUiSettings().setAllGesturesEnabled(false);
map.setMyLocationEnabled(true);
onAsyncLoad();
}
#Override
public void onResume() {
if (mapView != null) {
mapView.onResume();
}
super.onResume();
}
#Override
public void onLowMemory() {
if (mapView != null) {
mapView.onLowMemory();
}
super.onLowMemory();
}
public void onSaveInstanceState(Bundle outState) {
Log.i(TAG, "SAVING TO INSTANCE STATE");
//This MUST be done before saving any base class variables
final Bundle mapViewSaveState = new Bundle(outState);
if (mapView != null) { // May be null after onDestroView
mapView.onSaveInstanceState(mapViewSaveState);
outState.putBundle("mapViewSaveState", mapViewSaveState);
}
}
I am trying to get google maps v2 working in my app. I have seen several examples showing how you can open up SupportMapFragment inside an activity. The idea being that your activity will call setContentView(R.layout.map_layout); where map_layout.xml links to the fragment with the lines:
android:name="com.google.android.gms.maps.SupportMapFragment"
xmlns:map="http://schemas.android.com/apk/res-auto"
The "name=" line effectively says that "this layout is to be controlled by a fragment of type 'SupportMapFragment'".
My complication is that I am attempting to get the map to appear in an activity with tabs (implemented with actionbarsherlock). This means that whatever fragment corresponds to a tab selection must implement a TabListener. But SupportMapFragment doesn't. So now presumably I need to create a new fragment like so:
public class MyMapFragmentWithTabListener extends SupportMapFragment implements TabListener
{
But now I have got all confused about how to write the contents of MapFragmentWithTabListener in particular onCreateView... should I be inflating some layout? Surely I can't be inflating exactly the same map_layout.xml from the examples because that already declares that it is controlled by SupportMapFragment, whereas in this implementation it should be controlled by MyMapFragmentWithTabListener - do I need a slightly different xml file to inflate (if so, what should it look like?) - or should I be creating my view programatically?
I've done this in quite a few applications now. Instead of extending SupportMapFragment, you just create your own MapFragment. You can have your own layout, with a MapView view inside of it. The key is to route the lifecycle events of the Fragment to the MapView, and bobs your uncle.
Heres some example code:
MapFragment
package com.example.testapplication;
import java.util.concurrent.TimeUnit;
import com.google.android.gms.common.GooglePlayServicesNotAvailableException;
import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.MapView;
import com.google.android.gms.maps.MapsInitializer;
public class TestMapFragment extends Fragment {
private MapView mMapView;
#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.home_fragment, container, false);
mMapView = (MapView) view.findViewById(R.id.mapview);
// inflat and return the layout
mMapView.onCreate(savedInstanceState);
mMapView.onResume();// needed to get the map to display immediately
try {
MapsInitializer.initialize(getActivity());
} catch (GooglePlayServicesNotAvailableException e) {
e.printStackTrace();
}
GoogleMap googleMap = mMapView.getMap();
googleMap.getUiSettings().setMyLocationButtonEnabled(true);
return view;
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setRetainInstance(true);
}
/*
* 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 (null != mMapView)
mMapView.onResume();
}
#Override
public void onPause() {
super.onPause();
if (null != mMapView)
mMapView.onPause();
}
#Override
public void onDestroy() {
super.onDestroy();
if (null != mMapView)
mMapView.onDestroy();
}
#Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
if (null != mMapView)
mMapView.onSaveInstanceState(outState);
}
#Override
public void onLowMemory() {
super.onLowMemory();
if (null != mMapView)
mMapView.onLowMemory();
}
}
And the layout:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:map="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<com.google.android.gms.maps.MapView
android:id="#+id/mapview"
android:layout_width="match_parent"
android:layout_height="match_parent"
map:uiZoomControls="false" />
</RelativeLayout>
You can used this way.
public class NewActivity extends FragmentActivity {
private GoogleMap mMap;
SupportMapFragment mapFragment;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
this.requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.activit);
mapFragment = (SupportMapFragment)getSupportFragmentManager().findFragmentById(R.id.map);
if(isGooglePlayServicesIsInstalled(mContext)){
mMap = mapFragment.getMap();
mMap.setMapType(GoogleMap.MAP_TYPE_NORMAL);
mMap.getUiSettings().setCompassEnabled(true);
mMap.getUiSettings().setZoomControlsEnabled(true);
}else{
//display any toast message
//Global.Toast("Please First install Google Maps");
}
public static boolean isGooglePlayServicesIsInstalled(Context context){
int resultCode = GooglePlayServicesUtil.isGooglePlayServicesAvailable(context);
if (resultCode == ConnectionResult.SUCCESS)
return true;
else
return false;
}
Please check it out all the permission,api key and require all the thing.if you getting any error log then put as a comment.
Am trying to create and app with one activity but multiple fragment. i am using android.support.v4.* to build the fragment.
Each item i have created so far by extending Fragment, I want to use the google Map Api2 in my application,
All the tutoril i found so far adding the "SupportMapFragment" as an element to layout file.
"<fragment
class="com.google.android.gms.maps.SupportMapFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"/>"
But i cannot use this way because nested fragment not supporting, how can i use the google map api2 as a fragment in my application
use the mapview as suggested in Comments
public class InteractiveMapsWidget extends Fragment {
private MapView mMapView;
private GoogleMap mMap;
public void onCreate(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
Log.i(TAG, "ON CREATED");
Activity activity = getActivity();
if (activity != null) {
Bundle bundle = getArguments();
`
}
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
Log.i(TAG, "onCreateView");
new DataWorkerAsyncTask(getActivity()).execute(widgetId);
mMapView = (MapView) view.findViewById(R.id.map);
mMapView.onCreate(savedInstanceState);
setUpMapIfNeeded();
return view;
}
#Override
public void onResume() {
super.onResume();
mMapView.onResume();
setUpMapIfNeeded();
}
private void setUpMapIfNeeded() {
if (mMap == null) {
mMap = ((MapView) view.findViewById(R.id.map)).getMap();
if (mMap != null) {
setUpMap();
}
}
}
private void setUpMap() {
mMap.addMarker(new MarkerOptions().position(new LatLng(0, 0)).title("Marker"));
}
#Override
public void onPause() {
mMapView.onPause();
super.onPause();
}
#Override
public void onDestroy() {
mMapView.onDestroy();
super.onDestroy();
}
#Override
public void onLowMemory() {
super.onLowMemory();
mMapView.onLowMemory();
}
#Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
}
}
Layout
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:map="http://schemas.android.com/apk/res-auto"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<LinearLayout
android:id="#+id/root_container"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<com.google.android.gms.maps.MapView
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/map"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
</LinearLayout>
I'm trying to create a SupportMapFragment dynamically and to put it in a FrameLayout container.
My issue is that mMapFragment.getMap() returns null...
Anybody can help?
CenterMapFragment.java
public class CenterMapFragment extends Fragment {
private SupportMapFragment mMapFragment;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
return inflater.inflate(R.layout.center_map_fragment, container, false);
}
#Override
public void onActivityCreated (Bundle savedInstanceState){
super.onActivityCreated(savedInstanceState);
if (GooglePlayServicesUtil.isGooglePlayServicesAvailable(getActivity()) == ConnectionResult.SUCCESS) {
setUpMapIfNeeded();
}
}
private void setUpMapIfNeeded() {
if (mMapFragment == null) {
mMapFragment = SupportMapFragment.newInstance();
FragmentTransaction fragmentTransaction =
getChildFragmentManager().beginTransaction();
fragmentTransaction.replace(R.id.map, mMapFragment);
fragmentTransaction.commit();
setUpMap();
}
}
private void setUpMap() {
GoogleMap map = mMapFragment.getMap();
// map is null!
}
#Override
public void onResume()
{
super.onResume();
setUpMapIfNeeded();
}
}
center_map_fragment.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" >
<FrameLayout
android:id="#+id/map"
android:layout_width="match_parent"
android:layout_height="match_parent" >
</FrameLayout>
<Button
android:id="#+id/btn_loc"
android:layout_width="60dp"
android:layout_height="50dp"
android:layout_alignParentBottom="true"
android:layout_alignParentRight="true"
android:background="#drawable/locbtn" />
</RelativeLayout>
commit() on a FragmentTransaction does not perform its operations immediately. By the time you call setUpMap(), onCreateView() will not have been called on the SupportMapFragment, and hence there
will not yet be a map.
One approach is to not use nested fragments, electing instead to have CenterMapFragment extend SupportMapFragment, in which case getMap() should work any time after onCreateView() (e.g., onActivityCreated()).
In the following link MapView is used as CommonsWare suggests in the last part of his comment:
http://ucla.jamesyxu.com/?p=287
public class MapFragment extends Fragment {
MapView m;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// inflat and return the layout
View v = inflater.inflate(R.layout.map_fragment, container, false);
m = (MapView) v.findViewById(R.id.mapView);
m.onCreate(savedInstanceState);
return v;
}
#Override
public void onResume() {
super.onResume();
m.onResume();
}
#Override
public void onPause() {
super.onPause();
m.onPause();
}
#Override
public void onDestroy() {
super.onDestroy();
m.onDestroy();
}
#Override
public void onLowMemory() {
super.onLowMemory();
m.onLowMemory();
}
}
I hope these will be helpful.
Calling
fragmentTransaction.commit();
is asynchronous, the map won't be ready yet when you return from it. Simply call
getFragmentManager().executePendingTransactions();
as the next line, that will make it synchronous and will execute it for the next instruction to pick up the finished map all right. If you're worried about the time it takes, put the whole initialization into an AsyncTask and show a progress indicator to the user while the map is initializing.
I am trying to display a simple map in my Android application, using the MapView class.
I use the following onCreate method in my activity :
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
try {
MapsInitializer.initialize(this);
} catch (GooglePlayServicesNotAvailableException e) {
Log.e("Address Map", "Could not initialize google play", e);
}
MapView mapView = new MapView(this);
CameraUpdate camPos = CameraUpdateFactory.newLatLng(new LatLng(11.562276,104.920292));
mapView.getMap().moveCamera(camPos);
setContentView(mapView);
}
I have a NullPointerException, because the method mapView.getMap() returns null.
Don't understand why, Google play services are apparently present and initialized.
Could not get MapView to work, I finally ended using the class SupportMapFragment.
For those that it may help, here is the complete code of my activity :
public class AddressMap extends android.support.v4.app.FragmentActivity {
private final static int FRAGMENT_ID = 0x101;
private GoogleMap mMap;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
LinearLayout layout = new LinearLayout(this);
layout.setOrientation(LinearLayout.HORIZONTAL);
layout.setLayoutParams(new LinearLayout.LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT));
SupportMapFragment fragment = SupportMapFragment.newInstance();
layout.setId(0x101);
{
FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction();
fragmentTransaction.add(FRAGMENT_ID, fragment);
fragmentTransaction.commit();
}
setContentView(layout);
}
#Override
protected void onResume() {
super.onResume();
setUpMapIfNeeded();
}
private void setUpMapIfNeeded() {
if (mMap == null) {
mMap = ((SupportMapFragment) getSupportFragmentManager()
.findFragmentById(FRAGMENT_ID)).getMap();
if (mMap != null) {
mMap.moveCamera(
CameraUpdateFactory.newLatLngZoom(new LatLng(11.562276, 104.920292), 10));
}
}
}
}
Also, mapView.onCreate() must be called.
You are trying to access Google Maps Android v1 Api which is now deprecated, please use Google Map Android Api v2
I used it like this and it worked, this is with the new api:
compile 'com.google.android.gms:play-services-maps:10.2.6'
public class MapViewFragment extends Fragment{
public static final String TAG = MapViewFragment.class.getSimpleName();
MapView mapView;
GoogleMap map;
static MapViewFragment instance;
public static MapViewFragment newInstance(){
if(instance == null){
instance = new MapViewFragment();
return instance;
}else{
return instance;
}
}
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
Log.i(TAG, "onCreateView: " );
View view = inflater.inflate(R.layout.map_view_fragment, container, false);
mapView = (MapView) view.findViewById(R.id.mvMap);
if(mapView != null){
mapView.onCreate(null); //Don't forget to call onCreate after get the mapView!
mapView.getMapAsync(new OnMapReadyCallback() {
#Override
public void onMapReady(GoogleMap googleMap) {
map = googleMap;
//Do what you want with the map!!
}
});
MapsInitializer.initialize(this.getActivity());
}else{
Log.i(TAG, "onCreateView: mapView is null");
}
return view;
}
#Override
public void onResume() {
mapView.onResume();
super.onResume();
}
#Override
public void onDestroy() {
super.onDestroy();
mapView.onDestroy();
}
#Override
public void onLowMemory() {
super.onLowMemory();
mapView.onLowMemory();
}
}
And here is my layout:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent">
<com.google.android.gms.maps.MapView
android:id="#+id/mvMap"
android:layout_width="match_parent"
android:layout_height="match_parent">
</com.google.android.gms.maps.MapView>
</LinearLayout>