Reputation: 650
I have a dialog created as a dialogFragment that has it's own XML layout. Is it possible to embed a map inside the DialogFragment with a reference to it, so I can update it's location?
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.example.andrew.neighborlabour.CreateJobDialog">
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/colorPrimary"
android:orientation="horizontal">
<TextView
android:id="@+id/tvTitle"
android:text="Create Job"
android:textAppearance="@color/colorPrimaryDark"
android:textSize="24dp"
android:padding="20dp"
android:lines="2"
android:layout_gravity="left"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
</TextView>
</LinearLayout>
<ScrollView android:id="@+id/ScrollView01"
android:layout_width="fill_parent"
android:layout_height="400dp">
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<EditText
android:paddingLeft="20dp"
android:paddingRight="20dp"
android:paddingBottom="20dp"
android:layout_width="300dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:hint="Address"
android:id="@+id/etAddress"/>
<fragment xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="200dp"
android:id="@+id/map"
tools:context=".MapsActivity"
android:name="com.google.android.gms.maps.SupportMapFragment" />
</LinearLayout>
</ScrollView>
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Create Job"
android:id="@+id/btCreate"
android:onClick="Create"/>
</LinearLayout>
into the XML I can see the map but i'm unsure how to interact with it from my java code.
dialogFragment:
public class CreateJobDialog extends DialogFragment {
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.dialog_create_job, container, false);
return view;
}
}
to create the dialog:
CreateJobDialog createJobDialog = new CreateJobDialog();
createJobDialog.show(this.getFragmentManager(), "NoticeDialogFragment");
Upvotes: 3
Views: 5442
Reputation: 3530
Well, i got some several issue due to multimap with google api. So i think a complete answer for a full reusable dialog use should be something like this (base on a previous answer).
public class MapDialogFragment extends DialogFragment
implements OnMapReadyCallback{
GoogleMap mMap;
public MapDialogFragment() {
// Required empty public constructor
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View rootView = inflater.inflate(R.layout.fragment_map_edit_location, container, false);
return rootView;
}
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
FragmentManager fm = getChildFragmentManager();
SupportMapFragment mapFragment = (SupportMapFragment) fm.findFragmentByTag("mapFragment");
if (mapFragment == null) {
mapFragment = new SupportMapFragment();
FragmentTransaction ft = fm.beginTransaction();
ft.add(R.id.mapFragmentContainer, mapFragment, "mapFragment");
ft.commit();
fm.executePendingTransactions();
}
mapFragment.getMapAsync(this);
}
@Override
public void onMapReady(GoogleMap googleMap) {
mMap = googleMap;
mMap.setMapType(GoogleMap.MAP_TYPE_HYBRID);
LatLng latLng = new LatLng(37.7688472,-122.4130859);
mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(latLng,11));
MarkerOptions markerOptions = new MarkerOptions();
markerOptions.position(latLng);
markerOptions.title("Current Position");
markerOptions.icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_MAGENTA));
mMap.addMarker(markerOptions);
}
}
Then the xml file with google map (note that we use only the parent layout to avoid inflating a fragment inside another).
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/mapFragmentContainer"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
</LinearLayout>
The call from my fragment.
new MapDialogFragment().show(getActivity().getSupportFragmentManager(), null);
Hope it will help some people searching a dialog working EVEN in multimap context.
Upvotes: 1
Reputation: 829
I would add to the answer of @Daniel Nugent the implementation of the following code in the method onDestroyView()
.
@Override
public void onDestroyView() {
super.onDestroyView();
assert getFragmentManager() != null;
Fragment fragment = (getFragmentManager().findFragmentById(R.id.map));
FragmentTransaction ft = Objects.requireNonNull(getActivity()).getSupportFragmentManager().beginTransaction();
ft.remove(fragment);
ft.commit();
}
I followed the steps of his answer but was marking a 'FATAL EXCEPTION'. When opening> close> back open 'DialogFragment'.
Caused by: android.view.InflateException: Binary XML file line #44: Error inflating class fragment
Caused by: java.lang.IllegalArgumentException: Binary XML file line #44: Duplicate id 0x7f0900c3, tag null, or parent id 0x7f090067 with another fragment for com.google.android.gms.maps.SupportMapFragment.
Note: it could be useful for someone else with the same problem as me to follow this answer. I do not put my observation in comment, because I do not comply with the 50 reputation points.
Upvotes: 7
Reputation: 43322
This is pretty standard, just use the getMapAsync()
method to get a reference to the Google Map.
The only surprising thing was that I had to use getFragmentManager()
instead of getChildFragmentManager()
inside of the DialogFragment code. Normally when nesting a SupportMapFragment inside of a Fragment, you need to use the child FragmentManager, but apparently it's different for a DialogFragment.
Here's the DialogFragment code:
import android.support.v4.app.DialogFragment;
import com.google.android.gms.maps.CameraUpdateFactory;
import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.OnMapReadyCallback;
import com.google.android.gms.maps.SupportMapFragment;
import com.google.android.gms.maps.model.BitmapDescriptorFactory;
import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.maps.model.MarkerOptions;
public class MapDialogFragment extends DialogFragment
implements OnMapReadyCallback{
GoogleMap mMap;
public MapDialogFragment() {
// Required empty public constructor
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View rootView = inflater.inflate(R.layout.fragment_map_dialog, container, false);
SupportMapFragment mapFragment = (SupportMapFragment) getFragmentManager().findFragmentById(R.id.map);
mapFragment.getMapAsync(this);
return rootView;
}
@Override
public void onMapReady(GoogleMap googleMap) {
mMap = googleMap;
mMap.setMapType(GoogleMap.MAP_TYPE_HYBRID);
LatLng latLng = new LatLng(37.7688472,-122.4130859);
mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(latLng,11));
MarkerOptions markerOptions = new MarkerOptions();
markerOptions.position(latLng);
markerOptions.title("Current Position");
markerOptions.icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_MAGENTA));
mMap.addMarker(markerOptions);
}
}
Launching the DialogFragment:
new MapDialogFragment().show(getSupportFragmentManager(), null);
Result:
Upvotes: 9