I'm trying to create a basic activity with a google map fragment. Right now I have this:
public class MainScreen extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main_screen);
// add the map fragment to the activity
if (findViewById(R.id.fragment_container) != null) {
if (savedInstanceState != null) { return; }
getSupportFragmentManager().beginTransaction()
.add(R.id.fragment_container, new FragmentGoogle()).commit();
}
}
}
public class FragmentGoogle extends android.support.v4.app.Fragment {
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
return inflater.inflate(R.layout.map_google, container, false);
}
}
Which is producing this:
My question is: how can I interact with the fragment itself? Let's supposse I want to zoom in Sidney. Should I put the code in the MainScreen.class or in the Fragment.class? Which methods should I use? It's my first time working with fragments.
you don't need to create your own FragmentGoogle. You can use com.google.android.gms.maps.SupportMapFragment and controll it from you activity code.
in the layout:
<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="match_parent"
android:id="#+id/map"
tools:context=".MapsActivity"
android:name="com.google.android.gms.maps.SupportMapFragment" />
and then in the Activity code:
public class MapsActivity extends FragmentActivity implements OnMapReadyCallback {
private GoogleMap mMap;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_maps);
SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager()
.findFragmentById(R.id.map);
mapFragment.getMapAsync(this);
}
#Override
public void onMapReady(GoogleMap googleMap) {
mMap = googleMap;
// Add a marker in Sydney, Australia, and move the camera.
LatLng sydney = new LatLng(-34, 151);
mMap.addMarker(new MarkerOptions().position(sydney).title("Marker in Sydney"));
mMap.moveCamera(CameraUpdateFactory.newLatLng(sydney));
}
}
The code is taken from
this tutorial which is enough to start and use most of the features of the Google Maps Android API, just follow the steps :)
Lets say you have an empty activity in a new project.
do this :
creating premade android map activity
And then you ll get something like this :
your project structure
go to google maps api and do what they tell you to do in the (TODO)
Create an account and a project on google maps platform https://console.cloud.google.com/google/maps-apis/
Activate android development by clicking a button you ll have to look for it
and then go to key section to create new api key
go back to android studio and click the yellow xml file in the picture
past your key there
So by now the Map actvity should give you a real map and everything should work , you should see the map if you get to the map activity
but now what you want is to add that map inside your MainActivity .(i named it ActivityMain because MapActivity and MainActivity look the same )
Now all you need to do is copy past the fragment of the xml file activity_maps.xml without changing anything except for the id .
this is the activity_main.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"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/map1"
android:name="com.google.android.gms.maps.SupportMapFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MapsActivity" />
I tried adding a button here but i couldn't. So what i did is copy the fragment itself and put it inside the activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:gravity="center"
tools:context=".ActivityMain">
<Button
android:id="#+id/button1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Start" />
<fragment xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:map="http://schemas.android.com/apk/res-auto"
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"
tools:context=".MapsActivity" />
</LinearLayout>
I think these are all steps to create the picture you have in your question.
I hope this was useful not painful to read .
Related
I have created a standard Google Maps Activity in my app in Android Studio and the map works as expected.
My Activity is called 'NativeMap' and then the activity starts I see a ToolBar/AppBar at the top of the activity with the text "NativeMap".
The layout file for the activity is standard and calls a maps fragment:
<?xml version="1.0" encoding="utf-8"?>
<androidx.fragment.app.FragmentContainerView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:map="http://schemas.android.com/apk/res-auto"
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"
tools:context=".NativeMap">
</androidx.fragment.app.FragmentContainerView>
As such, there is no toolbar defined in the XML for me to reference or customize...
The onCreate for this activity seems very simple as well, so again I can only assume that there is a lot of stuff included in the background.
// public class NativeMap extends FragmentActivity implements OnMapReadyCallback {
public class NativeMap extends AppCompatActivity implements OnMapReadyCallback {
private static final String TAG = NativeMap.class.getSimpleName();
private GoogleMap mMap;
private ActivityNativeMapBinding binding;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
binding = ActivityNativeMapBinding.inflate(getLayoutInflater());
setContentView(binding.getRoot());
// Obtain the SupportMapFragment and get notified when the map is ready to be used.
SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager()
.findFragmentById(R.id.map);
if (mapFragment != null) mapFragment.getMapAsync(this);
}
#Override
public void onMapReady(GoogleMap googleMap) {
mMap = googleMap;
// Add a marker in Sydney and move the camera
LatLng sydney = new LatLng(-34, 151);
mMap.addMarker(new MarkerOptions().position(sydney).title("Marker in Sydney"));
mMap.moveCamera(CameraUpdateFactory.newLatLng(sydney));
}
}
(Note that I have switched this class to extend AppCompatActivity to get the bar to appear at the top, when it extends FragmentActivity no top bar appears at all.)
How can I access this toolbar or replace it with a standard toolbar.
I also want to add a drawer menu to this activity, but everything looks so abstracted via this fragment inclusion that I have no idea how to.
I've been Googling for about a week now and can't find anything that even seems to point me in the right direction with this.
I figured it out.
androidx.fragment.app.FragmentContainerView can only contain fragments, so the base container in the layout needed to be changed.
I changed it to a <androidx.drawerlayout.widget.DrawerLayout to allow the main menu drawer to be included. (called "_drawer" in the tree view below)
Inside the DrawerLayout I added a androidx.constraintlayout.widget.ConstraintLayout to contain the main layout components, including the map fragment and the toolbar. (The contraint layout is called "mainLayout" in the treeview below)
The toolbar was then added inside a com.google.android.material.appbar.AppBarLayout.
The map fragment was then added in a <fragment> tag below the AppBarLayout.
This works as expected.
The layout XML is now as follows:
<?xml version="1.0" encoding="utf-8"?>
<androidx.drawerlayout.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/_drawer"
android:animateLayoutChanges="true"
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.constraintlayout.widget.ConstraintLayout
android:id="#+id/mainLayout"
android:animateLayoutChanges="true"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.google.android.material.appbar.AppBarLayout
android:id="#+id/appBarLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="#style/AppTheme.AppBarOverlay"
app:layout_constraintTop_toTopOf="parent">
<androidx.appcompat.widget.Toolbar
android:id="#+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
app:popupTheme="#style/AppTheme.PopupOverlay">
<androidx.appcompat.widget.AppCompatImageView
android:id="#+id/top_logo"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:contentDescription="#string/app_logo"
app:srcCompat="#drawable/ic_app_top_logo" />
</androidx.appcompat.widget.Toolbar>
</com.google.android.material.appbar.AppBarLayout>
<fragment
android:id="#+id/map"
android:name="com.google.android.gms.maps.SupportMapFragment"
android:layout_width="match_parent"
android:layout_height="0dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/appBarLayout"
tools:context=".NativeMap" />
</androidx.constraintlayout.widget.ConstraintLayout>
<LinearLayout
android:id="#+id/_nav_view"
android:layout_width="320dp"
android:layout_height="match_parent"
android:layout_gravity="start"
android:background="#EEEEEE">
<include
android:id="#+id/drawerMenu"
layout="#layout/drawer_main" />
</LinearLayout>
</androidx.drawerlayout.widget.DrawerLayout>
I am using mapView and a SupportMapFragment to display the map in a fragment. On newer Android versions (I tested 8 and 9 on different devices) the map displays without any problem. However, on older Android versions (I tested 6 and 7) the map is showing a black screen (see black screen pic). The maps seems to work correctly though. I can click on it, routes are properly calculated an I can start navigation. So did I initialize the mapView / mapFragment wrong? How can I remove the black screen and get the mapView working on older Android versions?
I tried to initialize the mapView differently, but nothing seemed to do the trick. The map remains black. Since there is also no console output, regarding the black screen, I do not know how to proceed. Any help is greatly appreciated.
The MainActivity.java:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Mapbox.getInstance(this, getString(R.string.access_token));
setContentView(R.layout.activity_main);
(...)
// Create supportMapFragment
if (savedInstanceState == null) {
// Create fragment
final FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
// Build mapboxMap
MapboxMapOptions options = new MapboxMapOptions();
options.camera(new CameraPosition.Builder()
.target(new LatLng(-52.6885, -70.1395))
.zoom(9)
.build());
// Create map fragment
mapFragment = SupportMapFragment.newInstance(options);
// Add map fragment to parent container
transaction.add(R.id.container2, mapFragment, "com.mapbox.map");
transaction.commit();
navigationView.setCheckedItem(R.id.nav_home);
} else {
mapFragment = (SupportMapFragment) getSupportFragmentManager().findFragmentByTag("com.mapbox.map");
}
mapFragment.getMapAsync(new OnMapReadyCallback() {
#Override
public void onMapReady(#NonNull MapboxMap mapboxMap) {
MainActivity.this.mapboxMap = mapboxMap;
mapView = findViewById(R.id.mapView);
(...)
#Override
protected void onStart() {
super.onStart();
mapFragment.onStart();
}
// etc.
(...)
Part of the activity_main.xml containing the mapView and the container2 for the mapFragment:
<android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:openDrawer="start">
<android.support.constraint.ConstraintLayout
xmlns:mapbox="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<RelativeLayout
android:id="#+id/container2"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.mapbox.mapboxsdk.maps.MapView
android:id="#+id/mapView"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</RelativeLayout>
(...)
I expect the mapView/fragment to show properly not only in newer Android versions, but also in older Android versions.
I have created a new Android project with a Google Map activity defined as
public class MapsActivity extends FragmentActivity implements OnMapReadyCallback {
private GoogleMap mMap;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_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);
}
The Layout is this
<fragment xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:map="http://schemas.android.com/apk/res-auto"
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"
tools:context="com.example.alewe.myapplication.MapsActivity" />
The problem is :
i have created another activity and im trying to add the google map fragment inside it.
Using the
FragmentManager manager = getSupportFragmentManager();
manager.beginTransaction().replace(R.id.firstLayout,this,this.getTag());
doesnt work because i cant cast FragmentActivity to Fragment.
How can i add the google maps fragment just created inside another activity ?
Thanks
Change your layout (activity_maps) like this:
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.example.alewe.myapplication.MapsActivity"
android:id="#+id/main_view_map">
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="#+id/button"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintRight_toRightOf="parent"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:elevation="10dp"
app:fabSize="mini"
app:srcCompat="#drawable/ic_refresh_black_24dp"
android:layout_marginTop="16dp"
android:layout_marginEnd="16dp" />
<fragment xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:map="http://schemas.android.com/apk/res-auto"
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" />
</androidx.constraintlayout.widget.ConstraintLayout>
And don't use
FragmentManager manager = getSupportFragmentManager();
manager.beginTransaction().replace(R.id.firstLayout,this,this.getTag());
this code.
I tried the Hello World code from ArcGIS android SDK and followed all the steps but the map doesn't appear and instead I get a black mapview.
Here is the java code :
package com.example.user.arcgismap;
import android.app.Activity;
import android.os.Bundle;
import com.esri.android.map.MapView;
public class MainActivity extends Activity {
MapView mMapView;
// Called when the activity is first created.
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.content_main);
// After the content of this Activity is set, the map can be accessed programmatically from the layout.
mMapView = (MapView) findViewById(R.id.map);
}
#Override
protected void onPause() {
super.onPause();
// Call MapView.pause to suspend map rendering while the activity is paused, which can save battery usage.
if (mMapView != null)
{
mMapView.pause();
}
}
#Override
protected void onResume() {
super.onResume();
// Call MapView.unpause to resume map rendering when the activity returns to the foreground.
if (mMapView != null)
{
mMapView.unpause();
}
}
}
and here is the xml layout :
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="#dimen/activity_vertical_margin"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
app:layout_behavior="#string/appbar_scrolling_view_behavior"
tools:context="com.example.user.arcgismap.MainActivity"
tools:showIn="#layout/activity_main">
<com.esri.android.map.MapView
android:id="#+id/map"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
mapoptions.MapType="streets"
mapoptions.center="34.056215, -117.195668,"
mapoptions.ZoomLevel="16">
</com.esri.android.map.MapView>
</RelativeLayout>
can anyone help, what am I doing wrong ?
apparently the code is working well all I had to do was to reinstall the apk and wait a little bit for the map to load. I guess patience is a virtue.
Actually iam making an app which displays popular movies ( popular movie app project of udacity course) and i have two activites main activity and detail activity but when i tried to make my app run on a tablet it crashes and can't display even the main activity on launching the app and i dont know what is missing ....
Also , i want to know how can i specify that my app should run on different screen sizes for tablets..
MainActivity.java
public class MainActivity extends AppCompatActivity {
private static final String DETAILFRAGMENT_TAG ="DFTAG" ;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (findViewById(R.id.movie_detail_container) != null) {
mTwoPane = true;
if (savedInstanceState == null) {
getSupportFragmentManager().beginTransaction()
.replace(R.id.movie_detail_container, new MovieDetailFragment(),DETAILFRAGMENT_TAG)
.commit();
Log.v(LOG_TAG, "CRASH ");
}
} else {
mTwoPane = false;
}
MovieDetail.java
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_movie_detail);
if (savedInstanceState == null) {
getSupportFragmentManager().beginTransaction()
.add(R.id.movie_detail_container, new MovieDetailFragment())
.commit();
}
}
activity_main.xml
<fragment xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/fragment_movie"
android:name=".MoviesFragment"
tools:context=".MoviesFragment"
tools:layout="#android:layout/list_content"
android:layout_width="match_parent"
android:layout_height="match_parent"
/>
sw600dp\activity_main.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:baselineAligned="false"
android:divider="?android:attr/dividerHorizontal"
android:orientation="horizontal">
<fragment
android:id="#+id/fragment_movie"
android:name=".MoviesFragment"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="3" />
<FrameLayout
android:id="#+id/movie_detail_container"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="4" />
activity_movie_detail.xml
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/movie_detail_container"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MovieDetail"
tools:ignore="MergeRootFrame" />
LogCat
java.lang.RuntimeException: Unable to start activity ComponentInfo{.popularmovies/.popularmovies.MainActivity}: java.lang.NullPointerException
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2059)
I think you are not getting the xml resource reference correctly. try to add "movie_detail_container" in /mainActivity xml too. and then try
Both your activity_movie_detail.xml and activity_main.xml contains a view with same name "movie_detail_container". When you call
getSupportFragmentManager().beginTransaction()
.replace(R.id.movie_detail_container, new MovieDetailFragment(),DETAILFRAGMENT_TAG)
.commit();
It gets confused since the movie_detail_container of activity_movie_detail has not yet been inflated and is therefore null