I wrote a simple App with Two Activities, The First is my MainActivity and the Second is my MapsActivity.
The Code works perfectly in my MainActivity, when i press a Button i will get redirected to my MapsActivity with fixed LatLng and my actual Location.
Now i came to the conclusion that i want to implent a TabLayout (in Total 3 Tabs).
The First Tab should contain the Buttons and the functionality of my MainActivity
As already all Buttons and all the code is in my MainActivity i need to transfer it to the First Fragment.
This didnt work out, since im using alot of findViewById and the Fragment does not like that.
MainActivity:
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
private Button button;
private Button btnred;
private Button btnaura;
private double v1;
private double v12;
private double vend;
private double v1end;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
toolbar.setLogo(R.drawable.fvroth);
button = findViewById(R.id.btnroth);
btnred= findViewById(R.id.btnRednitz);
btnaura = findViewById(R.id.btnaurach);
btnaura.setOnClickListener(this);
button.setOnClickListener(this);
btnred.setOnClickListener(this);
ViewPager2 viewPager2 = findViewById(R.id.viewPager);
viewPager2.setAdapter(new weiherPageAdapter(this));
TabLayout tabLayout =findViewById(R.id.tabLayout);
TabLayoutMediator tabLayoutMediator= new TabLayoutMediator(
tabLayout, viewPager2, new TabLayoutMediator.TabConfigurationStrategy() {
#Override
public void onConfigureTab(#NonNull TabLayout.Tab tab, int position) {
switch (position){
case 0: {
tab.setText("Fliesgewässer");
tab.setIcon(R.drawable.ic_baseline_check_24);
break;
}
case 1: {
tab.setText("Weiher");
tab.setIcon(R.drawable.ic_baseline_account_circle_24);
break;
}
case 2: {
tab.setText("Schon-maß und Zeiten");
tab.setIcon(R.drawable.ic_baseline_announcement_24);
break;
}
}
}
}
);
tabLayoutMediator.attach();
}
public void openMapsActivity(){
Intent intent=new Intent(this,MapsActivity.class);
LatLng position= new LatLng(v1,v12);
intent.putExtra("Pos",position);
LatLng positionende = new LatLng(vend, v1end);
intent.putExtra("PosEnde",positionende);
startActivity(intent);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
#Override
public void onClick(View v) {
switch (v.getId()){
case R.id.btnroth:
v1= 49.21344;
v12= 11.171002;
vend= 49.211946;
v1end= 11.158726;
openMapsActivity();
break;
case R.id.btnRednitz:
v1= 49.250451;
v12= 11.084395;
vend= 49.269385;
v1end= 11.076057;
openMapsActivity();
break;
case R.id.btnaurach:
v1= 49.244672;
v12= 11.043886;
vend=49.254027;
v1end= 11.080881;
openMapsActivity();
break;
}
}
MapActivity
public class MapsActivity extends FragmentActivity implements OnMapReadyCallback {
Location currentLocation;
FusedLocationProviderClient fusedLocationProviderClient;
private static final int REQUEST_CODE = 101;
private GoogleMap mMap;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_maps);
fusedLocationProviderClient = LocationServices.getFusedLocationProviderClient(this);
fetchLastLocation();
// Obtain the SupportMapFragment and get notified when the map is ready to be used.
// Construct a GeoDataClient
}
private void fetchLastLocation() {
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this,new String[]
{Manifest.permission.ACCESS_FINE_LOCATION},REQUEST_CODE);
return;
}
Task<Location> task = fusedLocationProviderClient.getLastLocation();
task.addOnSuccessListener(new OnSuccessListener<Location>() {
#Override
public void onSuccess(Location location) {
if(location != null){
currentLocation = location;
Toast.makeText(getApplicationContext(),currentLocation.getLatitude()+""+currentLocation.getLongitude(),Toast.LENGTH_SHORT).show();
SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager()
.findFragmentById(R.id.map);
mapFragment.getMapAsync(MapsActivity.this);
}
}
});
}
/**
* Manipulates the map once available.
* This callback is triggered when the map is ready to be used.
* This is where we can add markers or lines, add listeners or move the camera. In this case,
* we just add a marker near Sydney, Australia.
* If Google Play services is not installed on the device, the user will be prompted to install
* it inside the SupportMapFragment. This method will only be triggered once the user has
* installed Google Play services and returned to the app.
*/
#Override
public void onMapReady(GoogleMap googleMap) {
mMap = googleMap;
// Add a marker in Sydney and move the camera
LatLng position = getIntent().getExtras().getParcelable("Pos");
LatLng positionende= getIntent().getExtras().getParcelable("PosEnde");
LatLng aktpos = new LatLng(currentLocation.getLatitude(),currentLocation.getLongitude());
mMap.addMarker(new MarkerOptions().position(position).title("Anfang"));
mMap.addMarker(new MarkerOptions().position(positionende).title("Ende"));
mMap.addMarker(new MarkerOptions().position(aktpos).title("ich").icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_AZURE)));
mMap.animateCamera(CameraUpdateFactory.newLatLngZoom(position,15),1000,null);
}
}
For Better understanding here a Picture of the App.
Related
I new on programming android apps. I want to display a map in one of the fragments that I created for a bottom navigation bar. However, I'm not sure what I should include in the the MainActivity.java, the fragment_map.xml, and the MapFragment.java.
I share my code to see if anyone could please help me to figure it out what I should include in each one.
Thanks :)
MapFragment.java
public class MapFragment extends Fragment implements OnMapReadyCallback {
private GoogleMap mMap;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Set the layout file as the content view.
setContentView(R.layout.activity_main);
// Get a handle to the fragment and register the callback.
MapFragment mapFragment = (MapFragment) getFragmentManager()
.findFragmentById(R.id.map);
mapFragment.getMapAsync(this);
}
private void getMapAsync(MapFragment mapFragment) {
}
private void setContentView(int activity_main) {
}
// Get a handle to the GoogleMap object and display marker.
#Override
public void onMapReady(GoogleMap googleMap) {
googleMap.addMarker(new MarkerOptions()
.position(new LatLng(0, 0))
.title("Marker"));
}
}
MainActivity.java
public class MainActivity extends AppCompatActivity {
private FragmentManager fragmentManager;
private Fragment mapFragment = new MapFragment();
private Fragment storyFragment = new StoryFragment();
private Fragment infoFragment = new InfoFragment();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
fragmentManager = getSupportFragmentManager();
fragmentManager.beginTransaction().add(R.id.body_container, mapFragment, null).commit();
fragmentManager.beginTransaction().add(R.id.body_container, storyFragment, null).commit();
fragmentManager.beginTransaction().add(R.id.body_container, infoFragment, null).commit();
BottomNavigationView bottomNavigationView = findViewById(R.id.bottom_navigation);
//bottomNavigationView.setSelectedItemId(R.id.mapsFragment);
bottomNavigationView.setOnItemSelectedListener(navListener);
}
private NavigationBarView.OnItemSelectedListener navListener = new NavigationBarView.OnItemSelectedListener(){
#Override
public boolean onNavigationItemSelected(#NonNull MenuItem item) {
switch (item.getItemId()){
case R.id.nav_map:
fragmentManager.beginTransaction().replace(R.id.body_container, mapFragment).commit();
break;
case R.id.nav_story:
fragmentManager.beginTransaction().replace(R.id.body_container, storyFragment).commit();
break;
case R.id.nav_info:
fragmentManager.beginTransaction().replace(R.id.body_container, infoFragment).commit();
break;
}
return true;
}
};
}
fragment_map.xml
<?xml version="1.0" encoding="utf-8"?>
<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="wrap_content"
android:layout_height="match_parent"/>
devs just a quick solution to the problem. I have a static listview of different highways and Maps activity. Now functionality I want to implement is that when the user clicks on any highway which is present in the listview markers are displayed on the map. Same functionality like e.g there is a list of known places like FB HQ Eifel tower etc when the user clicks on the button the marker moves to a particular location. I just want this kind of functionality through listview. What I have done so far is given below.
My list Coding:
public class Motorway_List extends AppCompatActivity {
Intent i;
#Override
protected void onCreate(Bundle savedInstanceState) {
ListView list;
String[] maintitle ={
"Motorway 1","Motorway 2",
"Motorway 3",
"Motorway 9"
};
Integer[] imgid={
R.drawable.1,R.drawable.2,
R.drawable.3,R.drawable.9,
};
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_motorway__list);
Motorway_list_adapter adapter=new Motorway_list_adapter(this, maintitle,imgid);
list=(ListView)findViewById(R.id.list);
list.setAdapter(adapter);
list.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
// TODO Auto-generated method stub
if(position == 0) {
//code specific to first list item
// Toast.makeText(getApplicationContext(),"Place Your First Option Code",Toast.LENGTH_SHORT).show();
//this is where I call maps activity but it's open full map activity I want to click to open specific markers.
i = new Intent(Motorway_List.this,EmergencyMapsActivity.class);
startActivity(i);
}
else if(position == 1) {
//code specific to 2nd list item
Toast.makeText(getApplicationContext(),"Place Your Second Option Code",Toast.LENGTH_SHORT).show();
}
else if(position == 2) {
Toast.makeText(getApplicationContext(),"Place Your Third Option Code",Toast.LENGTH_SHORT).show();
}
else if(position == 3) {
Toast.makeText(getApplicationContext(),"Place Your Forth Option Code",Toast.LENGTH_SHORT).show();
}
else if(position == 4) {
Toast.makeText(getApplicationContext(),"Place Your Fifth Option Code",Toast.LENGTH_SHORT).show();
}
}
});
}
}
And My maps Coding:
public class EmergencyMapsActivity extends FragmentActivity implements OnMapReadyCallback
{
private static final int REQUEST_LOCATION_PERMISSION = 1 ;
private GoogleMap mMap;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_emergency_maps);
// Obtain the SupportMapFragment and get notified when the map is ready to be used.
SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager()
.findFragmentById(R.id.map);
mapFragment.getMapAsync(this);
}
#Override
public void onMapReady(GoogleMap googleMap) {
mMap = googleMap;
enableMyLocation();
// Add a marker in Sydney and move the camera
LatLng islamabad = new LatLng(33.692390, 73.055848);
mMap.addMarker(new MarkerOptions().position(islamabad).title("Marker in Islamabad"));
mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(islamabad,10f));
}
private void enableMyLocation() {
if (ContextCompat.checkSelfPermission(this,
Manifest.permission.ACCESS_FINE_LOCATION)
== PackageManager.PERMISSION_GRANTED) {
mMap.setMyLocationEnabled(true);
} else {
ActivityCompat.requestPermissions(this, new String[]
{Manifest.permission.ACCESS_FINE_LOCATION},
REQUEST_LOCATION_PERMISSION);
}
}
#Override
public void onRequestPermissionsResult(int requestCode,
#NonNull String[] permissions,
#NonNull int[] grantResults) {
// Check if location permissions are granted and if so enable the
// location data layer.
switch (requestCode) {
case REQUEST_LOCATION_PERMISSION:
if (grantResults.length > 0
&& grantResults[0]
== PackageManager.PERMISSION_GRANTED) {
enableMyLocation();
break;
}
}
}
}
public class Motorway_List extends AppCompatActivity {
Intent i;
#Override
protected void onCreate(Bundle savedInstanceState) {
ListView list;
String[] maintitle ={
"Motorway 1","Motorway 2",
"Motorway 3",
"Motorway 9"
};
Integer[] imgid={
R.drawable.1,R.drawable.2,
R.drawable.3,R.drawable.9,
};
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_motorway__list);
Motorway_list_adapter adapter=new Motorway_list_adapter(this, maintitle,imgid);
list=(ListView)findViewById(R.id.list);
list.setAdapter(adapter);
list.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
//TODO SENDING POSITION WHICH ITEM IS CLICK to MAP ACTIVITY
i = new Intent(Motorway_List.this,EmergencyMapsActivity.class);
i.putExtra("which",position);
startActivity(i);
});
}
}
Seconde Activity
Bundle bundle = getIntent().getExtras();
int position = (int) bundle.get("which");
if (position==0){
// motoway 1 Coding
}else if (position==1){
//motorway 2 coding
}else if(position ==2){
//motorway 3 coding
}else if(position == 3){
//motoway 4 coding
}
}
I want to make an app that has on the main screen a ViewPager with a map and a profile section. Therefore, for position = 0 in the ViewPager, there is the map and for position = 1, there is the profile.
For each one of those two "sections" on the main screen, I have two activities: the map.xml with the MapActivity.java and the profile.xml with Profile.java. Both of those are inflated in the EnumFrag java class, depending on the position ( you see there an if ).
I have two issues:
The first one is that when I try to slide left or right, the map moves, not the ViewPager to the next slide. I tried to put a shape on the edge, but it is not working like the slide gesture is passing through the shape. Any help here, please?
The second is related to the first one, the MapActivity.java class is not even running because onCreate is not running (I put a Toast there so display something and nothing happened). Any help, please? (I create the map class object).
map.xml contains a simple fragment with an id of map.
MapActivity.java:
public class MapActivity extends FragmentActivity implements OnMapReadyCallback {
private GoogleMap map;
private Location me;
private FusedLocationProviderClient fusedLocationProviderClient;
private static final int REQUEST_CODE = 101;
#Override
protected void onCreate(Bundle savedInstanceState) {
Toast.makeText(this, "hey din onCreate", Toast.LENGTH_SHORT).show();
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_map);
fusedLocationProviderClient = LocationServices.getFusedLocationProviderClient(this);
getLastLocation();
}
private void getLastLocation() {
if(ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED){
ActivityCompat.requestPermissions(this,new String[]{Manifest.permission.ACCESS_FINE_LOCATION},REQUEST_CODE);
return;
}
Toast.makeText(getApplicationContext(), "hey...", Toast.LENGTH_SHORT).show();
Task<Location> task = fusedLocationProviderClient.getLastLocation();
task.addOnSuccessListener(new OnSuccessListener<Location>() {
#Override
public void onSuccess(Location location) {
if(location != null){
me = location;
SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map);
mapFragment.getMapAsync(MapActivity.this);
}
else
Toast.makeText(getApplicationContext(), "Deschide-ti locatia", Toast.LENGTH_SHORT).show();
}
});
}
#Override
public void onMapReady(GoogleMap googleMap) {
map = googleMap;
MapStyleOptions mapStyleOptions= MapStyleOptions.loadRawResourceStyle(this,R.raw.map_style);
googleMap.setMapStyle(mapStyleOptions);
LatLng point = new LatLng(me.getLatitude(),me.getLongitude());
MarkerOptions markerOptions = new MarkerOptions().position(point).title("Me");
googleMap.animateCamera(CameraUpdateFactory.newLatLng(point));
googleMap.animateCamera(CameraUpdateFactory.newLatLngZoom(point,16));
googleMap.addMarker(markerOptions);
}
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String[] permissions, #NonNull int[] grantResults) {
if (requestCode == REQUEST_CODE) {
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
getLastLocation();
}
}
}
}
Profile.java
public class Profile extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_profile);
EditText username = findViewById(R.id.usernameProfile);
username.setText(MainScreen.getUsername());
}
}
EnumFragment.java
public class EnumFragments extends PagerAdapter {
private Context context;
public EnumFragments(Context context) {
this.context = context;
}
#NonNull
#Override
public Object instantiateItem(#NonNull ViewGroup container, int position) {
LayoutInflater layoutInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View view;
MapActivity mapActivity = new MapActivity();
switch (position){
case 0:
view = layoutInflater.inflate(R.layout.activity_profile,null);
break;
default:
view = layoutInflater.inflate(R.layout.activity_map,null);
break;
}
ViewPager viewPager = (ViewPager)container;
viewPager.addView(view);
return view;
}
#Override
public void destroyItem(#NonNull ViewGroup container, int position, #NonNull Object object) {
ViewPager viewPager = (ViewPager)container;
View view = (View) object;
viewPager.removeView(view);
}
#Override
public int getCount() {
return 2;
}
#Override
public boolean isViewFromObject(#NonNull View view, #NonNull Object object) {
return view == object;
}
}
MainScreen.java
public class MainScreen extends AppCompatActivity {
private static String username;
private ViewPager viewPager;
private EnumFragments enumFragments;
private static int userID;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main_screen);
Bundle extras = getIntent().getExtras();
userID = extras.getInt("userID");
username = extras.getString("username");
viewPager = findViewById(R.id.mainSlider);
EnumFragments enumFragments = new EnumFragments(this);
viewPager.setAdapter(enumFragments);
}
public static int getUserID() {
return userID;
}
public static String getUsername() {
return username;
}
#Override
public void onBackPressed() {
//Nothing
}
}
Why you don't add the MapActivity into the MainScreen Activity. You even don't use the MapActivity in your PagerAdapter class. I would make an other attribute in the constructor of your PagerAdapter, after this :
private MapActivity current;
public EnumFragments(MapActivity map_activity)
{
this.current = map_activity;
}
then I would put a getter method in the map_activity, wich returns a view, where you can see the current GoogleMap or other features.
Your problem is that you don't use the new MapActivity...
I hope that may helps you
So I've made a MapActivity which shows a MapBox map.
Then I load in all my markers(pins, which are eventually Point objects with longitude and latitude) from the database into a List< Features > markerCoordinates. markerCoordinates is then given through GeoJsonSource().
Now all my markers are displayed on the map.
Now I can't figure out how to make a marker clickable, and when clicked I need to obtain the ID of the marker so I can later on redirect to another Activity and then load in all data based on that ID. This ID of the pin needs to be the same as the ID from the database.
Mapbox Documentation doesn't really helped me out with this problem.
Does any one know how to implement this?
MapActivity.java
public class MapActivity extends AppCompatActivity {
private MapView mapView;
DatabaseHelper myDb;
private BottomNavigationView.OnNavigationItemSelectedListener mOnNavigationItemSelectedListener
= new BottomNavigationView.OnNavigationItemSelectedListener() {
#Override
public boolean onNavigationItemSelected(#NonNull MenuItem item) {
switch (item.getItemId()) {
case R.id.navigation_moments:
Intent intent = new Intent(MapActivity.this, MapActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION);
startActivity(intent);
break;
case R.id.navigation_addmoment:
Intent intent2 = new Intent(MapActivity.this, AddMomentActivity.class);
intent2.addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION);
startActivity(intent2);
break;
}
return false;
}
};
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
myDb = new DatabaseHelper(this);
Mapbox.getInstance(this, "pk.eyJ1IjoiaGlqYWNrbWFuaWFjIiwiYSI6ImNqdWlyb3E3NzE5bjc0Zm9lOHpta3AzajMifQ.ithKXW2RvhRzlPqXWBexyg");
setContentView(R.layout.activity_map);
BottomNavigationView navigation = (BottomNavigationView) findViewById(R.id.navigation);
navigation.setOnNavigationItemSelectedListener(mOnNavigationItemSelectedListener);
mapView = findViewById(R.id.mapView);
mapView.onCreate(savedInstanceState);
mapView.getMapAsync(new OnMapReadyCallback() {
#Override
public void onMapReady(#NonNull MapboxMap mapboxMap) {
mapboxMap.setStyle(Style.MAPBOX_STREETS, new Style.OnStyleLoaded() {
#Override
public void onStyleLoaded(#NonNull Style style) {
// Importing markers from database
List<Feature> markerCoordinates = new ArrayList<>();
loadPins(markerCoordinates);
// Adding markers on the map
style.addSource(new GeoJsonSource("source-id",
FeatureCollection.fromFeatures(markerCoordinates)));
// Some styling below
style.addImage("marker-icon-id",
BitmapFactory.decodeResource(
MapActivity.this.getResources(), R.drawable.mapbox_marker_icon_default));
SymbolLayer symbolLayer = new SymbolLayer("layer-id", "source-id");
symbolLayer.withProperties(
PropertyFactory.iconImage("marker-icon-id")
);
style.addLayer(symbolLayer);
}
});
}
});
}
// Switch from map to moments
#Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.header_items, menu);
final MenuItem listItem = menu.findItem(R.id.list_menu);
listItem.setVisible(true);
listItem.setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
#Override
public boolean onMenuItemClick(MenuItem item) {
Intent intent = new Intent(MapActivity.this, MomentsActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION);
startActivity(intent);
return true;
}
});
return true;
}
// Reading the Database, appending each row to allMarkers
public void loadPins(List<Feature> allMarkers) {
Cursor res = myDb.getAllData();
if(res.getCount() == 0) {
// Error message
return;
}
while(res.moveToNext()) {
double longitude = Double.parseDouble(res.getString(4));
double latitude = Double.parseDouble(res.getString(5));
if(longitude == 0 || latitude == 0) {
continue;
} else {
allMarkers.add(Feature.fromGeometry(
Point.fromLngLat(
longitude,
latitude
)
));
}
}
}
#Override
public void onStart() {
super.onStart();
mapView.onStart();
}
#Override
public void onResume() {
super.onResume();
mapView.onResume();
}
#Override
public void onPause() {
super.onPause();
mapView.onPause();
}
#Override
public void onStop() {
super.onStop();
mapView.onStop();
}
#Override
public void onLowMemory() {
super.onLowMemory();
mapView.onLowMemory();
}
#Override
protected void onDestroy() {
super.onDestroy();
mapView.onDestroy();
}
#Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
mapView.onSaveInstanceState(outState);
}
}
First, you should implement the onMapClick or onMapLongClick methods, so that you can handle all map clicks and retrieve the data you need.
The steps to get the marker Id on every click are roughly these:
Check whether the click was on a marker or elsewhere.
You can do this by querying the source layer (your GeoJsonSource) and checking whether there is a feature nearby the clicked spot.
If a feature was found, get the property you need.
You could use feature.getProperties() to get all the properties or feature.getStringProperty("name_of_the_property") to get a specific one. See more here.
Check this example to see how to implement all of this.
I am having issues with GoogleMap due to the fact that it gets the map asynchronously using MapView#getMapAsync.
I am experiencing a NullPointerException due to the #getMapAsync not returning in time when my Activity is passing markers to the GoogleMap object.
Can this be done synchronously or is there a better solution? Adding it to the fragment bundle would not work for me as the activity may pass the fragment markers after the #commit()
GoogleMapsFragment
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// inflate and return the layout
View v = inflater.inflate(R.layout.fragment_google_map, container,
false);
ButterKnife.bind(this, v);
mMapView.onCreate(savedInstanceState);
mMapView.onResume();// needed to get the map to display immediately
try {
MapsInitializer.initialize(getActivity().getApplicationContext());
} catch (Exception e) {
e.printStackTrace();
}
Bundle bundle = getArguments();
if(bundle != null){
initialMarkers = bundle.getParcelableArrayList("markers");
}
mMapView.getMapAsync(new OnMapReadyCallback() {
#Override
public void onMapReady(GoogleMap googleMap) {
mGoogleMap = googleMap;
if (mCameraPos != null) {
mGoogleMap.moveCamera(CameraUpdateFactory.newCameraPosition(mCameraPos));
mCameraPos = null;
} else {
//Set default camera position over the United States.
CameraPosition cameraPosition = new CameraPosition.Builder()
.target(new LatLng(37.09024, -95.712891)).zoom(3).build();
mGoogleMap.moveCamera(CameraUpdateFactory
.newCameraPosition(cameraPosition));
}
}
});
return v;
}
Activity
#OnClick(R.id.loadListOrMapButton)
public void onClickChangeView() {
FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
if (mLocationListViewFrag.isVisible()) {
if (mGoogleMapFrag == null) {
mGoogleMapFrag = new GoogleMapFragment();
fragmentTransaction.add(R.id.fragment_container, mGoogleMapFrag);
}
bListMapButton.setText(getString(R.string.list));
fragmentTransaction.hide(mLocationListViewFrag).show(mGoogleMapFrag);
} else {
bListMapButton.setText(getString(R.string.map));
fragmentTransaction.hide(mGoogleMapFrag).show(mLocationListViewFrag);
}
fragmentTransaction.commit();
fragmentManager.executePendingTransactions();
updateDisplay();
}
UpdateDisplay
public void updateDisplay() {
if (mLocationListViewFrag != null && mLocationListViewFrag.isVisible()) {
Log.d(TAG, "Update Tax Location ListView");
mLocationListViewFrag.setLocations(mLocations);
} else if (mGoogleMapFrag != null && mGoogleMapFrag.isVisible()) {
Log.d(TAG, "Update Google Maps Markers");
//Convert locations to markers to display.
mGoogleMapFrag.clearMarkers();
for (LocationObj aLocation : mLocations) {
mGoogleMapFrag.addMarker(new MarkerOptions().position(
new LatLng(Double.valueOf(aLocation.getLat()), Double.valueOf(aLocation.getLng()))).title(aLocation.getName()));
mGoogleMapFrag.fitBounds();
}
}
}
You should move the code that handles the markers to be within the OnMapReadyCallback (https://developers.google.com/android/reference/com/google/android/gms/maps/OnMapReadyCallback) that you pass to #getMapAsync(OnMapReadyCallback callback). This will ensure the markers aren't placed until the map is available.
EDIT for additional info
Ultimately you have to solve the problem of "what do I do if someone makes #onClickChangeView get called when the map isn't ready?" From a user experience perspective, the loadListOrMapButton shouldn't even be shown until the map finishes loading. You should disable the button by default, then make this button available from within your OnMapReadyCallback. You could either grey out the button (google for "android disable button" for examples) or you could actually hide/show it with View#setVisibility.
Non-recommended approach
Although I'm hesitant to suggest it, you could instead just check if the GoogleMap is ready: from within your OnMapReadyCallback set a boolean that your outside activity can check. Something like
private boolean mapIsReady = false;
mMapView.getMapAsync(new OnMapReadyCallback() {
#Override
public void onMapReady(GoogleMap googleMap) {
// your normal code here
mapIsReady = true;
}
});
public boolean mapIsReady() {
return mapIsReady;
}
Then in the activity
#OnClick(R.id.loadListOrMapButton)
public void onClickChangeView() {
// check for null and all that jazz
if (mapsFragment.mapIsReady()) {
// updateDisplay and everything
} else {
// make a toast or something asking them to try later.
}
}
xml
<com.google.android.gms.maps.MapView
android:id="#+id/mapview"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:apiKey="#string/google_app_id"
android:clickable="true">
</com.google.android.gms.maps.MapView>
MainActivity.java
public class MainActivity extends AppCompatActivity implements OnMapReadyCallback {
LatLng sydney = new LatLng(33.8650, 151.2094);
MapView mapView;
GoogleMap map;
#Override
protected void onCreate(Bundle bundle) {
super.onCreate(bundle);
setContentView(R.layout.activity_main);
mapView = (MapView) findViewById(R.id.mapview);
mapView.getMapAsync(this);
MapsInitializer.initialize(this); /* initialize method should be called when we are not sure that map will be loaded before using it. It initialises the map.*/
mapView.onCreate(null);
mapView.onResume();
}
#Override
public void onMapReady(GoogleMap googleMap) {
map = googleMap;
map.addMarker(new MarkerOptions().position(sydney).draggable(true));
}
}