I need to load a google map into fragment. Here's my code and it's not working.
class busFragment : Fragment(), OnMapReadyCallback{
private lateinit var mMap: GoogleMap
companion object {
var mapFragment : SupportMapFragment?=null
val TAG: String = busFragment::class.java.simpleName
fun newInstance() = busFragment()
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
}
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?): View? {
// Inflate the layout for this fragment
var rootView = inflater.inflate(R.layout.fragment_bus, container, false)
childFragmentManager.findFragmentById(R.id.map) as? SupportMapFragment
mapFragment?.getMapAsync(this)
return rootView
}
override fun onMapReady(googleMap: GoogleMap?) {
mMap = googleMap!!
}
}
I added meta tag, dependencies in gradle and manifest. also give internet permission.
<meta-data
android:name="com.google.android.geo.API_KEY"
android:value="YOUR_API_KEY"/>
<uses-permission android:name="android.permission.INTERNET" />
implementation 'com.google.android.gms:play-services-maps:17.0.1'
Here's my xml file of that fragment. In this I used map view.
<androidx.constraintlayout.widget.ConstraintLayout 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"
tools:context="busFragment">
<!-- TODO: Update blank fragment layout -->
<com.google.android.gms.maps.MapView
android:id="#+id/map"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:layout_editor_absoluteX="-1dp"
tools:layout_editor_absoluteY="114dp" />
</androidx.constraintlayout.widget.ConstraintLayout>
This is because mapFragment does not initialize.
Replace this
childFragmentManager.findFragmentById(R.id.map) as? SupportMapFragment
mapFragment?.getMapAsync(this)
With this
mapFragment = childFragmentManager.findFragmentById(R.id.map) as? SupportMapFragment
mapFragment?.getMapAsync(this)
Related
I have simple DialogWindow
XML:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="300dp"
android:layout_height="150dp"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:orientation="vertical">
<fragment
android:id="#+id/nav_host_fragment_activity_main"
android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:defaultNavHost="true"
app:navGraph="#navigation/navigation"/>
</LinearLayout>
Code:
class DialogWindowBuyingStock(context: Context, private val viewModel: MainViewModel, private val stock: Stock) : AppCompatDialog(context) {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
supportRequestWindowFeature(Window.FEATURE_NO_TITLE)
setContentView(R.layout.buy_stock_dialogwindow)
}
}
In which i have some fragments for example the Main one:
class MainFragment : Fragment() {
private var _binding: MainFragmentBinding? = null
private val binding get() = _binding!!
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View {
val homeViewModel =
ViewModelProvider(this)[MainFragmentViewModel::class.java]
_binding = MainFragmentBinding.inflate(inflater, container, false)
val root: View = binding.root
return root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
main_buy_button.setOnClickListener {
Navigation.findNavController(view).navigate(R.id.action_mainFragment_to_buyFragment)
}
}
override fun onDestroyView() {
super.onDestroyView()
_binding = null
}
}
It works perfectly for the first time i start Dialog Window, but when i close it and start again, i got this llegalArgumentException: Binary XML file line #20: Duplicate id 0x7f080136, tag null, or parent id 0xffffffff with another fragment for androidx.navigation.fragment.NavHostFragment
How can i fix that?
I'm trying to create implement a Google-Map in android using fragment :
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
return inflater.inflate(R.layout.fragment_map_test, container, false)
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
//the line below get's error
val mapFragment = view?.findViewById<View>(R.id.sp_map_test) as SupportMapFragment
mapFragment.getMapAsync(this)
}
My XML :
<?xml version="1.0" encoding="utf-8"?>
<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="match_parent"
tools:context=".MapTestFragment">
<fragment
android:id="#+id/sp_map_test"
android:name="com.google.android.gms.maps.SupportMapFragment"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
But it can't find the SupportMap Fragment. How can I resolve this ?
I have tried this also - val mapFragment = parentFragmentManager.findFragmentById(R.id.sp_map_test) as SupportMapFragment
null cannot be cast to non-null type com.google.android.gms.maps.SupportMapFragment
Insted of
val mapFragment = view?.findViewById<View>(R.id.sp_map_test) as SupportMapFragment
and
val mapFragment = parentFragmentManager.findFragmentById(R.id.sp_map_test) as SupportMapFragment
Use
val mapFragment = supportFragmentManager
.findFragmentById(R.id.map) as SupportMapFragment
Reference MapFragment Referance
You have to put it in onCreateView
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
val view = inflater.inflate(R.layout.fragment_map_test, container, false)
val mapFragment = view?.findViewById<View>(R.id.sp_map_test) as SupportMapFragment
mapFragment.getMapAsync(this)
}
or you also create Support Map Fragment from template
In Android Studio select New -> Fragment -> Google Map Fragment
I am making an app that has many map interactions, and one of them is seeing a little map inside an Activity where the users will be able to select a point in the map and send a request to our API.
My problem is, after I made the fragment to load the google maps and added it to the activity that should show it, the Activity itself started to crash when landing on it.
Debugging the app, I see the crash occurs on the 'SetContentView' of the Activity.
Here is the XML for the activity:
<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout
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"
tools:context=".FaleConoscoActivity">
<com.google.android.material.appbar.AppBarLayout
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:theme="#style/AppTheme.AppBarOverlay">
<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"/>
</com.google.android.material.appbar.AppBarLayout>
<LinearLayout
android:id="#+id/ll_main_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:orientation="vertical"
android:paddingLeft="25dp"
android:paddingTop="70dp"
android:paddingRight="25dp"
android:paddingBottom="40dp"
app:layout_anchor="#+id/ll_main_layout"
app:layout_anchorGravity="center">
//Some EditTexts and Buttons
<FrameLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<fragment
android:id="#+id/fragment"
android:name="com.example.dumper2.MapFragment"
tools:layout="#layout/fragment_map"
android:layout_width="match_parent"
android:layout_height="294dp" />
</FrameLayout>
</LinearLayout>
...
</androidx.coordinatorlayout.widget.CoordinatorLayout>
Kotlin code for the activity:
class CadastroDePontoActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_cadastro_de_ponto)
}
//Some other interactions
}
And here are the XML and Kotlin for the fragment:
<FrameLayout 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"
tools:context=".MapFragment">
<fragment
android:name="com.google.android.gms.maps.SupportMapFragment"
android:id="#+id/mapFrag"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</FrameLayout>
Kotlin:
class MapFragment : Fragment(), OnMapReadyCallback {
private var param1: String? = null
private var param2: String? = null
private var listener: OnFragmentInteractionListener? = null
private lateinit var mMap: GoogleMap
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
arguments?.let {
param1 = it.getString(ARG_PARAM1)
param2 = it.getString(ARG_PARAM2)
}
}
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
// Inflate the layout for this fragment
val rootView = inflater.inflate(R.layout.fragment_map, container,
false)
val mapFragment = childFragmentManager.findFragmentById(R.id.mapFrag)as SupportMapFragment
mapFragment.getMapAsync(this)
return rootView
}
override fun onAttach(context: Context) {
super.onAttach(context)
if (context is OnFragmentInteractionListener) {
listener = context
} else {
throw RuntimeException(context.toString() + " must implement
OnFragmentInteractionListener")
}
}
override fun onDetach() {
super.onDetach()
listener = null
}
interface OnFragmentInteractionListener {
// TODO: Update argument type and name
fun onFragmentInteraction(uri: Uri)
}
override fun onMapReady(googleMap: GoogleMap) {
mMap = googleMap
}
companion object {
/**
* Use this factory method to create a new instance of
* this fragment using the provided parameters.
*
* #param param1 Parameter 1.
* #param param2 Parameter 2.
* #return A new instance of fragment MapFragment.
*/
// TODO: Rename and change types and number of parameters
#JvmStatic
fun newInstance(param1: String, param2: String) =
MapFragment().apply {
arguments = Bundle().apply {
putString(ARG_PARAM1, param1)
putString(ARG_PARAM2, param2)
}
}
}
}
Without the crashlog it's just guessing, but I don't see your activity extending OnFragmentInteractionListener, so in onAttach it would throw a RuntimeException.
My project has a tabbar, each of them shows a different fragment.
One of them is a fragment which carries another one from google maps and I can't find a way to make it work.
The main error (apparently) is that
this.childFragmentManager.findFragmentById(R.id.map) as
SupportMapFragment
returns null.
My code is this.
Fragment which has the map
class SpotListFragment : SupportMapFragment(), OnMapReadyCallback {
private lateinit var mMap: GoogleMap
lateinit var api : Api
lateinit var localStorage: LocalStorage
override fun onMapReady(googleMap: GoogleMap) {
mMap = googleMap
// Add a marker in Sydney and move the camera
val sydney = LatLng(-34.0, 151.0)
mMap.addMarker(MarkerOptions().position(sydney).title("Marker in Sydney"))
mMap.moveCamera(CameraUpdateFactory.newLatLng(sydney))
}
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?): View? {
val view: View = inflater!!.inflate(R.layout.fragment_spot_list, container, false)
view.borrarToken.setOnClickListener {
this.localStorage.deleteAll()
val intent = Intent(activity?.applicationContext!!, LoginActivity::class.java)
startActivity(intent)
}
val mapFragment = this.childFragmentManager.findFragmentById(R.id.map) as SupportMapFragment
mapFragment.getMapAsync(this)
return view
}
The fragment xml
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout 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"
xmlns:design="http://schemas.android.com/apk/res-auto"
tools:context=".Fragments.SpotListFragment"
android:orientation="vertical"
android:background="#color/white">
<fragment xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/map"
android:name="com.google.android.gms.maps.SupportMapFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
/>
<Button
android:id="#+id/borrarToken"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Borrar token"/>
<ListView
android:layout_gravity="bottom|center"
android:id="#+id/spotsListView"
android:layout_width="match_parent"
android:layout_height="245dp"
android:paddingBottom="60dp"
android:textColor="#color/black"
/>
</FrameLayout>
tabbar activity.
class MainNavActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val spotListFragment = SpotListFragment.newInstance()
openFragment(spotListFragment)
navigationView.setOnNavigationItemSelectedListener {
when(it.itemId) {
R.id.spotsListNav -> {
val spotListFragment = SpotListFragment.newInstance()
openFragment(spotListFragment)
true
}
R.id.searchNav -> {
true
}
R.id.createSpotNav -> {
val createSpotFragment = CreateSpotFragment.newInstance()
openFragment(createSpotFragment)
true
}
R.id.feedNav -> {
true
}
R.id.profileNav -> {
true
}
else -> {
false
}
}
}
}
private fun openFragment(fragment: Fragment) {
val transaction = supportFragmentManager.beginTransaction()
transaction.replace(R.id.container, fragment)
transaction.addToBackStack(null)
transaction.commit()
}
}
I wish you can help me, I really don't know what to do.
Thanks!
Get rid of this. in this line of code:
old:
val mapFragment = this.childFragmentManager.findFragmentById(R.id.map) as SupportMapFragment
new:
val mapFragment = childFragmentManager.findFragmentById(R.id.map) as SupportMapFragment
I'm trying to code my current app in Kotlin, but I get null cannot be casted to non-null type. I've tried a lot of different stuff, but I keep getting the same problem. Not sure what to do. Any help would be appreciated!
Code:
class MapsActivity : AppCompatActivity(), OnMapReadyCallback {
private lateinit var mMap: GoogleMap
private lateinit var button: Button
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_maps)
val mapFragment = supportFragmentManager
.findFragmentById(R.id.mapFragment) as SupportMapFragment
mapFragment.getMapAsync(this)
}
override fun onMapReady(googleMap: GoogleMap) {
mMap = googleMap;
setUpMap();
}
fun setUpMap() {
val et = findViewById<EditText>(R.id.editText);
val et2 = findViewById<EditText>(R.id.editText2);
val lat = et.getText().toString().toDouble();
val lng = et2.getText().toString().toDouble();
//val ll = LatLng(lat, lng)
button = findViewById(R.id.button) as Button
button.setOnClickListener {
goToLocation(lat, lng, 11.0f);
}
}
fun goToLocation(lat:Double, lng:Double, zoom:Float) {
val ll = LatLng(lat, lng);
val update = CameraUpdateFactory.newLatLngZoom(ll, zoom);
mMap.addMarker(MarkerOptions().position(ll).title("Marquette, Michigan"))
mMap.moveCamera(update);
}
XML:
<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="match_parent"
android:orientation="vertical"
android:paddingBottom="16dp"
android:paddingLeft="16dp"
android:paddingRight="16dp"
android:paddingTop="16dp"
tools:layout="#layout/activity_maps">
<EditText
android:id="#+id/editText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ems="10"
android:inputType="textPersonName" />
<EditText
android:id="#+id/editText2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ems="10"
android:inputType="textPersonName" />
<Button
android:id="#+id/button"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Submit"/>
<!-- android:onClick="locate"/> -->
<fragment
android:layout_width="match_parent"
android:layout_height="match_parent"
android:name="com.google.android.gms.maps.SupportMapFragment"
android:id="#+id/mapFragment"
/>
Logs:
Caused by: kotlin.TypeCastException: null cannot be cast to non-null type com.google.android.gms.maps.SupportMapFragment
at com.example.nrice.mapsproject.MapsActivity.onCreate(MapsActivity.kt:38)
Try This
val mapFragment = childFragmentManager.findFragmentById(R.id.map_frag) as SupportMapFragment
mapFragment.getMapAsync(this)
The compilation error is pointing to the following line in your code:
val mapFragment = supportFragmentManager
.findFragmentById(R.id.mapFragment) as SupportMapFragment
Here, you are typecasting something which is nullable, i.e. the return value of findFragmentById, to something that you have defined as non-nullable type, i.e. SupportMapFragment
Ideally, you should read about Kotlin null handling. It is quick read and should not take time and will clear your understanding here.
And, when you come back, you will see that there are more than one of ways of fixing your code, such as:
(activity.supportFragmentManager.findFragmentById(fragmentId) as SupportMapFragment?)?.let {
it.getMapAsync(this)
}
Quick tip: The difference between a nullable and non-nullable type in Kotlin is a ? postfixed to the type. So, here, SupportMapFragment? specifies that the type is SupportMapFragment and it can be null.
if you are using SupportMapFragment in a Fragment
you have to write "childFragmentManager.findFragmentById(R.id.myMap)" statement in
override fun onViewCreated(view: View, savedInstanceState: Bundle?)
not in
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View?
val mapFragment = supportFragmentManager.findFragmentById(R.id.mapFragment) as? SupportMapFragment
mapFragment?.getMapAsync(this)
For reference, you should read this
fix here in kotlin
private lateinit var mMap: GoogleMap
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val mapFragment: SupportMapFragment? = map as SupportMapFragment?
mapFragment?.getMapAsync(this)
}
override fun onMapReady(googleMap: GoogleMap?) {
if (googleMap != null) {
mMap = googleMap
}
val sydney = LatLng(-34.0, 151.0)
mMap.addMarker(MarkerOptions().position(sydney).title("Marker in Sydney"))
mMap.moveCamera(CameraUpdateFactory.newLatLng(sydney))
}