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.
Related
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);
}
this is my activity
public class FindPeopleFragment extends Fragment implements OnMapReadyCallback {
private GoogleMap googleMap;
MapFragment fragment;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_find_people, container, false);
initilizeMap();
return rootView;
}
#TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1)
private void initilizeMap() {
MapFragment fragment = (MapFragment) getChildFragmentManager().findFragmentById(R.id.map1);
if (fragment != null) {
fragment.getMapAsync(this);
}
}
#Override
public void onMapReady(GoogleMap googleMap) {
LatLng marker = new LatLng(44.797283, 20.460663);
googleMap.moveCamera(CameraUpdateFactory.newLatLngZoom(
new LatLng(44.797283, 20.460663), 12));
googleMap.addMarker(new MarkerOptions()
.position(new LatLng(44.797283, 20.460663))
.icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_AZURE)));
googleMap.setMyLocationEnabled(true);
}
#TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1)
#Override
public void onPause() {
final FragmentManager fragManager = this.getFragmentManager();
final Fragment fragment = fragManager.findFragmentById(R.id.map1);
if (fragment != null) {
fragManager.beginTransaction().remove(fragment).commit();
super.onPause();
}
}
#Override
public void onDestroy() {
super.onDestroy();
final FragmentManager fragManager = this.getFragmentManager();
final Fragment fragment = fragManager.findFragmentById(R.id.map1);
if (fragment != null) {
fragManager.beginTransaction().remove(fragment).commit();
}
}
}
I am using navigation drawer to show the map. my map is working but the marker on it does not show. I have used all permission and created the xml file well. I don't know what is the problem, I can't find a solution for this anywhere. I think I am having problem as I am using fragment, but I need it as I am using navigation drawer. please anybody? give me a solution, I'm stuck at this
You should implement onMapReadyCallback, you should set marker when map is ready. Once an instance of this interface is set on a MapFragment or MapView object, the onMapReady(GoogleMap) method is triggered when the map is ready to be used and provides a non null instance of GoogleMap.
The onMapReady() and method might not being called. Try to implement SupportMapFragment object that you retrieved from the XML layout. Then, call getMapAsync().
supportMapFragment.getMapAsync(new OnMapReadyCallback() {
#Override
public void onMapReady(final GoogleMap googleMap) {
// ...
}
});
I have another class called CadActivity where i define the Tittle mark using a EditText. How can i use this information inside onMapLongClick?
Any help will be great :)
public class MapaActivity extends FragmentActivity implements GoogleMap.OnMapLongClickListener {
GoogleMap map;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.mapa);
android.support.v4.app.FragmentManager myFragment = getSupportFragmentManager();
SupportMapFragment meusupFragment = (SupportMapFragment)myFragment.findFragmentById(R.id.map);
map = meusupFragment.getMap();
map.setMyLocationEnabled(true);
map.setOnMapLongClickListener(this);
}
#Override
public void onMapLongClick(LatLng coord) {
//Intent cadmap = new Intent(this,CadastrarActivity.class);
//startActivity(cadmap);
map.addMarker(new MarkerOptions()
.position(coord)
.title("")
.icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_BLUE)));
}
}
You just need to reference it in the method, like so (notice the EditText variable, the call to get the layout reference and then setting the title using the text in it):
public class MapaActivity extends FragmentActivity implements GoogleMap.OnMapLongClickListener {
GoogleMap map;
EditText myText;
#Override protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.mapa);
android.support.v4.app.FragmentManager myFragment = getSupportFragmentManager();
SupportMapFragment meusupFragment = (SupportMapFragment)myFragment.findFragmentById(R.id.map);
myText = (EditText)myFragment.findFragmentById(R.id.name_of_your_edit_text);
map = meusupFragment.getMap();
map.setMyLocationEnabled(true);
map.setOnMapLongClickListener(this);
}
#Override public void onMapLongClick(LatLng coord) {
//Intent cadmap = new Intent(this,CadastrarActivity.class);
//startActivity(cadmap);
map.addMarker(new MarkerOptions()
.position(coord)
.title(myText.getText().toString())
.icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_BLUE)));
}
}
I am creating an App where I want to switch between my CustomMapFragment and a ListFragment. If I start the App and call replaceFragment:
private void replaceFragment(final Fragment fragment) {
final FragmentManager fragmentManager = mActivity.getFragmentManager();
fragmentManager.beginTransaction()
.replace(R.id.main_content_frame, fragment)
.commit();
}
with replaceFragment(new CustomMapFragment()) the Map looks like it should.
The CustomMapFragment is a Fragment where I replace a FrameLayout with the native MapFragment, to have it separated from the code.
If I call the replace method again on button click or something, with a different Fragment (the ListFragment for example), the FrameLayout gets replaced with this, everything is fine.
If I now try to replace it again with the CustomMapFragment, the exact same call like on the beginning, the Map is loaded but it is missing every Marker and every Setting I have done in the CustomMapFragment.
CustomMapFragment:
public class CustomMapFragment extends BaseFragment {
private static final String LOG_TAG = PosMapFragment.class.getSimpleName();
private MapFragment mMapFragment;
private GoogleMap mMap;
private ImageLoader mImageLoader;
private Context mContext;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mContext = getActivity();
final RequestQueue reqQueue = Volley.newRequestQueue(mContext);
mImageLoader = new ImageLoader(reqQueue, new BitmapLruCache(mContext));
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
return inflater.inflate(R.layout.maps_fragment, container, false);
}
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
mMapFragment = MapFragment.newInstance();
replaceFragment(mMapFragment);
}
private void postMapInitialisation() {
new View(getActivity()).post(new Runnable() {
#Override
public void run() {
addTestMarker(0, 0, "http://www.jimis-cyberstore.com/store/media/gp_batman_tshirts.jpg");
addTestMarker(10, 10, "http://img.netzwelt.de/software/icons/2012/8842/android-sdk.png");
addTestMarker(50, 50, "http://fs02.androidpit.info/ali/x84/4053084-1374511678988-80x80.png");
addTestMarker(5, 0, "http://im.wk.io/images/77e3e40/kitkat-chromium-ubernimmt-in-android.jpeg");
addTestMarker(0, 10, "http://www.mchme.de/cms/kategorien/18_Software/dateien/fb_logo_80.jpg");
addTestMarker(15, 5, "http://navigator.ptvgroup.com/uploads/pics/PTV_Navigator_Android_Windows2_80x80px_01.png");
}
});
}
#Override
public void onResume() {
super.onResume();
setUpMapIfNeeded();
postMapInitialisation();
EventBusProvider.getInstance().register(this);
}
private void replaceFragment(final Fragment fragment) {
final FragmentManager fragmentManager = getFragmentManager();
fragmentManager.beginTransaction()
.replace(R.id.maps, fragment)
.commit();
}
private void setUpMapIfNeeded() {
if (mMap == null) {
mMap = mMapFragment.getMap();
if (mMap != null) {
mMap.setMyLocationEnabled(true);
mMap.setInfoWindowAdapter(this);
mMap.setOnInfoWindowClickListener(this);
}
}
}
private void addTestMarker(final double lat, final double lng, String url){
if(mMap != null){
final NetworkImageMarker networkImageMarker = new NetworkImageMarker(mContext, url);
final Marker marker = mMap.addMarker(networkImageMarker.getMarkerOptions(lat, lng, mImageLoader));
networkImageMarker.setMarker(marker);
networkImageMarker.setReloadListener(new OnReloadListener() {
#Override
public void reAddNetworkImageMarker(Bitmap bitmap) {
mMap.addMarker(networkImageMarker.getMarkerOptions(lat, lng, bitmap));
}
});
}
}
#Subscribe
public void onLocationChanged(final LocationChangedEvent event) {
centerMap(event.mLocation);
}
private void centerMap(Location location){
double latitude = location.getLatitude();
double longitude = location.getLongitude();
LatLng latLng = new LatLng(latitude, longitude);
centerMapAtLocation(latLng);
}
private void centerMapAtLocation(LatLng location) {
mMap.moveCamera(CameraUpdateFactory.newLatLng(location));
mMap.animateCamera(CameraUpdateFactory.zoomTo(14));
}
}
The main layout is just a FrameLayout, which get replaced for different Fragments. I also tried to load just one Fragment where the CustomMapFragment and the ListFragment are loaded at the same time, with two FrameLayouts, so they are stacked over each other, but it ends up in the same behavior.
It seems there is something wrong with the MapFragment (not the SupportMapFragment).
loading MapFragment at the beginning = MapFragment looks perfect
MapFragment -> ListFragment -> MapFragment = MapFragment is an empty Map
ListFragment -> MapFragment = MapFragment is an empty Map
MapFragment -> MapFragment = MapFragment is an empty Map
Because you are trying to replace fragments inside of another fragment, you should use getChildFragmentManager() instead of getFragmentManager() in your replace method.
private void replaceFragment(final Fragment fragment) {
final FragmentManager fragmentManager = getChildFragmentManager();
fragmentManager.beginTransaction()
.replace(R.id.maps, fragment)
.commit();
}
Unfortunately getChildFragmentManager() is only supported for api lvl >= 17, so you will probably have to use the android-support-v4 library.
I have a question and a problem. First of all I don't know is this possible:
I have a fragment activity with tabs. On one tab (which is a fragment) I have a map with a hidden list of items. Map is putted in a frame of that fragment. The list is downloaded and on a button press is visible again. On a map I have markers that represents that items.
My problem is this: I always get map to be null when a use getMap() from a fragment that I put in a frame.
Is this possible? And if not what do you recommend? Thanks in advance.
EDITED
public class MapExplore extends Fragment{
private FrameLayout frame;
private ListView list;
private String api_key;
private GoogleMap map;
private MapExploreAdapter adapter;
private SupportMapFragment map_fragment;
#Override
public void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
api_key = Configuration.get_prefereence_string(getActivity(), "user_activation_key", null);
adapter = new MapExploreAdapter();
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.map_explore, null);
frame = (FrameLayout) view.findViewById(R.id.frameMap);
return view;
}
#Override
public void onActivityCreated(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onActivityCreated(savedInstanceState);
setUpMapFragment();
}
private void setUpMapFragment(){
if(map_fragment == null){
map_fragment = SupportMapFragment.newInstance();
FragmentTransaction ft = getActivity().getSupportFragmentManager().beginTransaction();
ft.add(frame.getId(), map_fragment, Utils.MAP_FRAGMENT_TAG);
ft.commit();
}
}
private void setUpMap(){
Log.i("SET UP MAP", "Started");
if(map == null){
map = ((SupportMapFragment) map_fragment).getMap();
}
if(map != null){
map.moveCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(Utils.SF_LAT, Utils.SF_LON), 13));
}
}
#Override
public void onResume() {
// TODO Auto-generated method stub
super.onResume();
setUpMap();
}
I edited my question with some code...
If you could post some of you code it would be easier to diagnose your problem:
meantime try creating your SupportMap fragment dynamically as follows:
mMapFragment = new SupportMapFragment() {
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
GoogleMap map = mMapFragment.getMap();
if (map != null) {
//Your initialization code goes here
}
}
};
Altenative approach to use Mapview inside fragment as follows:
public class Yourfragment extends Fragment {
private MapView mMapView;
private GoogleMap mMap;
private Bundle mBundle;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View inflatedView = inflater.inflate(R.layout.map_fragment, container, false);
try {
MapsInitializer.initialize(getActivity());
} catch (GooglePlayServicesNotAvailableException e) {
// TODO handle this situation
}
mMapView = (MapView) inflatedView.findViewById(R.id.map);
mMapView.onCreate(mBundle);
setUpMapIfNeeded(inflatedView);
return inflatedView;
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mBundle = savedInstanceState;
}
private void setUpMapIfNeeded(View inflatedView) {
if (mMap == null) {
mMap = ((MapView) inflatedView.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 onResume() {
super.onResume();
mMapView.onResume();
}
#Override
public void onPause() {
super.onPause();
mMapView.onPause();
}
#Override
public void onDestroy() {
mMapView.onDestroy();
super.onDestroy();
}
}
And put map view in XML as follows:
<com.google.android.gms.maps.MapView
android:id="#+id/map"
android:layout_width="match_parent"
android:layout_height="match_parent" />
Here is a link to the official documentation for MapView