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
Related
Here is the kotlin file of the fragment:
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle? ): View? {
val view = inflater.inflate(R.layout.fragment_blank, container, false)
view.textView1 <- Here is the problem
return view
}
Down here is xml file of the fragment. I hope it's all right...
<?xml version="1.0" encoding="utf-8"?>
<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"
android:background="#color/purple_200"
tools:context=".BlankFragment">
<TextView
android:id="#+id/textView1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="1"
android:gravity="center"
android:textSize="80sp" />
</FrameLayout>
textView = findViewById(R.id.yourId);
and next you can use it
Actually findViewById() is not available on the Fragment class.
However, you can use inflated view to access the findViewById() as shown on this example.
class MyFragment : Fragment() {
lateinit var textView: TextView
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
// Inflate the layout for this fragment
val view = inflater.inflate(R.layout.fragment_my, container, false)
//use view to access findViewById() method
textView = view.findViewById(R.id.textView1)
textView.text = "Test 1"
return view
}
}
That said the recommended way would be to use Databinding or View Binding
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 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)
First Fragment's code
class MainFragment : Fragment() {
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
// Inflate the layout for this fragment
val mainInflater = inflater.inflate(R.layout.fragment_main, container, false)
return mainInflater
}
fun thisdata():String{
return "Hello from MainFragment"
}
}
First Fragment XML
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout 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=".MainFragment">
<EditText
android:id="#+id/etSavedData"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true"
android:layout_marginTop="60dp"
android:hint="Enter the Text"/>
<Button
android:id="#+id/btnSaveData"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true"
android:layout_marginTop="120dp"
android:text="Save"/>
</RelativeLayout>
Main Activity's code
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
//Set replace Main Activity content with the Fragment1 content
val mainFragment = MainFragment()
supportFragmentManager.beginTransaction().add(R.id.contain_fragment, mainFragment).commit()
val thedata = mainFragment.thisdata()
Log.e("Main Frag to Activity", thedata)
btnSaveData.setOnClickListener {
val secondFragment = SecondFragment()
supportFragmentManager.beginTransaction().add(R.id.contain_fragment, secondFragment).commit()
}
}
}
Main Activity XML
<?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:id="#+id/contain_fragment"
tools:context=".MainActivity">
</RelativeLayout>
Second Fragment's code
class SecondFragment : Fragment() {
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
// Inflate the layout for this fragment
val secondInflater = inflater.inflate(R.layout.fragment_second, container, false)
return secondInflater
}
}
Second Fragment XML
<?xml version="1.0" encoding="utf-8"?>
<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"
android:background="#android:color/holo_blue_dark"
tools:context=".SecondFragment">
<!-- TODO: Update blank fragment layout -->
<TextView
android:id="#+id/tvDisplayText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
tools:text="Text displayed here." />
</FrameLayout>
Following Exception showing up in Logcat
Caused by: java.lang.NullPointerException: Attempt to invoke virtual
method 'void
android.widget.Button.setOnClickListener(android.view.View$OnClickListener)'
on a null object reference
at com.example.demo2.MainActivity.onCreate(MainActivity.kt:22)*
You either need to move your btnSaveData button into the MainActivity, or you should move the onClickListener into the MainFragment, along with some other changes. Something like:
class MainFragment : Fragment() {
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
// Inflate the layout for this fragment
val mainInflater = inflater.inflate(R.layout.fragment_main, container, false)
btnSaveData.setOnClickListener {
val secondFragment = SecondFragment()
activity.supportFragmentManager.beginTransaction().add(R.id.contain_fragment, secondFragment).commit()
}
return mainInflater
}
fun thisdata():String{
return "Hello from MainFragment"
}
}
**Thanks Tash, that actually make sense, unfortunately it was still showing the same exception but I finally manage to resolve the issue by doing the following. **
class MainFragment : Fragment() {
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
// Inflate the layout for this fragment
val mainInflater = inflater.inflate(R.layout.fragment_main, container, false)
mainInflater.btnSaveData.setOnClickListener {
val secondFragment = SecondFragment()
secondFragment?.let {
activity?.supportFragmentManager?.beginTransaction()?.replace(R.id.contain_fragment, secondFragment)?.commit()
}
}
return mainInflater
}
fun thisdata():String{
return "Hello from MainFragment"
}
}
I'm trying to access a WebView from a Fragment and kotlin keeps on saying:
kotlin.TypeCastException: null cannot be cast to non-null type android.webkit.WebView
I have tried to make it null as default then init it but that does not work either. Any suggestions on how I can make it work?
My code:
private lateinit var webView: WebView
override fun onCreateView(inflater: LayoutInflater?, container: ViewGroup?, savedInstanceState: Bundle?): View? {
val view = inflater!!.inflate(R.layout.editor_edit_fragment, container, false)
webView = view.findViewById(R.id.webview) as WebView
resumeWebView()
return view
}
xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:android="http://schemas.android.com/apk/res/android">
<WebView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/webview" />
</LinearLayout>
You need to run onCreateView first, then onViewCreated to set up WebView.
class FragmentWebview : Fragment() {
lateinit var contentView: View
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
contentView = inflater.inflate(R.layout.fragment_fragment_webview, container, false)
return contentView
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
val webview = contentView.findViewById<WebView>(R.id.myWebview)
val url = "http://google.com"
val webSettings = myWebview.settings
webSettings.javaScriptEnabled = true
webSettings.domStorageEnabled = true
webview.webViewClient = WebViewClient()
webview.loadUrl(url)
}
}