unable to inflate fragment when initializing a View from activity
I am fiddling with kotlin for the first time and I have found that whenener I try to initialize a fragment on the main view it throws an exception when it loads
Caused by: android.view.InflateException: Binary XML file line #59 in com.example.firstapplication:layout/activity_main: Binary XML file line #59 in com.example.firstapplication:layout/activity_main: Error inflating class fragment Caused by: android.view.InflateException: Binary XML file line #59 in com.example.firstapplication:layout/activity_main: Error inflating class fragment Caused by: java.lang.IllegalStateException: no start destination defined via app:startDestination for com.example.firstapplication:id/main_navigation
line 59 has
app:navGraph="@navigation/main_navigation"
main_fragment.kt
package com.example.firstapplication
import android.app.DatePickerDialog
import android.os.Bundle
import androidx.fragment.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Button
import android.widget.EditText
import android.widget.TextView
import android.widget.Toast
import androidx.core.view.isVisible
import kotlinx.android.synthetic.main.action_bar.*
import kotlinx.android.synthetic.main.activity_main.*
import java.text.SimpleDateFormat
import java.util.*
// TODO: Rename parameter arguments, choose names that match
// the fragment initialization parameters, e.g. ARG_ITEM_NUMBER
private const val ARG_PARAM1 = "param1"
private const val ARG_PARAM2 = "param2"
/**
* A simple [Fragment] subclass.
* Use the [main_fragment.newInstance] factory method to
* create an instance of this fragment.
*/
class main_fragment : Fragment() {
// TODO: Rename and change types of parameters
private var param1: String? = null
private var param2: String? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
arguments?.let {
param1 = it.getString(ARG_PARAM1)
param2 = it.getString(ARG_PARAM2)
}
var buttonClickChangeText: Button = getView()?.findViewById(R.id.buttonClickChangeText) as Button
var textView: TextView = getView()?.findViewById(R.id.textView) as TextView
var datePickedText: EditText = getView()?.findViewById(R.id.datePickedText) as EditText
//var textView = findViewById(R.id.textView) as TextView
var clickCounter:Int=0
buttonClickChangeText.setOnClickListener{
clickCounter++
//clickDatePicker(it)
if(ContainsNoLetters(datePickedText.text.toString()))
{
/*if(IsDate(datePickedText.text.toString()))*/
var calendar = Calendar.getInstance()
val day:Int=calendar.get(Calendar.DAY_OF_MONTH)
val month:Int =(calendar.get(Calendar.MONTH)+ 1)
val year:Int =calendar.get(Calendar.YEAR)
var dayStr:String=if(day.toString().length==1) "0${day}" else day.toString()
var monthStr:String=if(month.toString().length==1) "0${month}" else month.toString()
//val formatter = DateTimeFormatter.ofPattern("\"dd-MM-yyyy", Locale.US)
//val birthday = LocalDate.parse("${dayStr}-${monthStr}-${year}", formatter)
val todayDate = SimpleDateFormat("dd-MM-yyyy").parse("${dayStr}-${monthStr}-${year}")
val birthday = SimpleDateFormat("dd-MM-yyyy").parse(datePickedText.text.toString())
val difference =((todayDate.getTime()/1000)- (birthday.getTime()/1000)) + 7200
//val currentDate:Date= sdf.format()
textView.text = "Desde ${datePickedText.text} han pasado\n" +
"$difference segundos o ${difference/60} minutos o\n${(difference/60)/60} horas o ${((difference/60)/60)/24} dias"
}
//Toast.makeText(this@MainActivity,"Clicked",Toast.LENGTH_SHORT).show()
buttonClickChangeText.isVisible=false
datePickedText.isVisible= false
}
datePickedText.setOnFocusChangeListener(View.OnFocusChangeListener { view, b ->
if(b)selDate(view)
})
imageMenu.setOnClickListener({
navigationsidemenu.isVisible=!navigationsidemenu.isVisible
})
}
fun IsDate(str: String):Boolean{
return str.contains("^(?:(?:31(\\/|-|\\.)(?:0?[13578]|1[02]))\\1|(?:(?:29|30)(\\/|-|\\.)(?:0?[13-9]|1[0-2])\\2))(?:(?:1[6-9]|[2-9]\\d)?\\d{2})\$|^(?:29(\\/|-|\\.)0?2\\3(?:(?:(?:1[6-9]|[2-9]\\d)?(?:0[48]|[2468][048]|[13579][26])|(?:(?:16|[2468][048]|[3579][26])00))))\$|^(?:0?[1-9]|1\\d|2[0-8])(\\/|-|\\.)(?:(?:0?[1-9])|(?:1[0-2]))\\4(?:(?:1[6-9]|[2-9]\\d)?\\d{2})\$")
}
fun ContainsNoLetters(str:String):Boolean
{
return !str.contains("[a-zA-Z]+")
}
fun selDate(view:View){
var datePickedText:TextView? = getView()?.findViewById(R.id.datePickedText)
var calendar:Calendar = Calendar.getInstance()
var day:Int = calendar.get(Calendar.DAY_OF_MONTH);
var month:Int =calendar.get(Calendar.MONTH)
var year:Int= calendar.get(Calendar.YEAR)
DatePickerDialog(view.context, DatePickerDialog.OnDateSetListener { datePicker, y, m, d->
month=m;
day=d;
year=y;
month+=1;
var dayStr:String=if(day.toString().length==1) "0${day}" else day.toString()
var monthStr:String=if(month.toString().length==1) "0${month}" else month.toString()
//Toast.makeText(this,"${dayStr}-${monthStr}-${year}", Toast.LENGTH_SHORT).show()
datePickedText?.setText("${dayStr}-${monthStr}-${year}")
},year,month,day).show()
var dayStr:String=if(day.toString().length==1) "0${day}" else day.toString()
month+=1;
var monthStr:String=if(month.toString().length==1) "0${month}" else month.toString()
// var yearStr:String=if(year.toString().length==2) "20${year}" else year.toString()
var date:Date? =SimpleDateFormat("dd-MM-yyyy").parse("${dayStr}-${monthStr}-${year}");
datePickedText?.clearFocus()
}
fun clickDatePicker(view:View ){
var selectedDay:Int;var selectedMonth:Int;var selectedYear:Int;
val calendar: Calendar=Calendar.getInstance()
val day:Int =calendar.get(Calendar.DAY_OF_MONTH)
val month:Int =calendar.get(Calendar.MONTH)
val year:Int =calendar.get(Calendar.YEAR)
DatePickerDialog(view.context, DatePickerDialog.OnDateSetListener {
datePicker, y, m, d-> selectedYear =y; selectedDay=d; selectedMonth=m;
// Toast.makeText(this@MainActivity,"SELECTED: ${y}/${m}/${d}", Toast.LENGTH_SHORT).show()
},year,month,day).show()
}
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
// Inflate the layout for this fragment
return inflater.inflate(R.layout._main_fragment, container, false)
}
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 main_fragment.
*/
// TODO: Rename and change types and number of parameters
@JvmStatic
fun newInstance(param1: String, param2: String) =
main_fragment().apply {
arguments = Bundle().apply {
putString(ARG_PARAM1, param1)
putString(ARG_PARAM2, param2)
}
}
}
}
main_fragment
<?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"
android:id="@+id/main_fragment"
tools:context=".main_fragment">
<TextView
android:id="@+id/textView"
android:name="com.example.firstapplication.textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="50dp"
android:layout_marginLeft="130dp"
android:gravity="center_vertical"
android:background="@drawable/gradient_background_color"
android:orientation="vertical"
android:paddingLeft="40dp"
android:paddingRight="40dp"
android:text="Texto"
android:textColor="#000000"
android:textSize="15dp"
app:layout_constraintVertical_bias="0.015" />
<Button
android:id="@+id/buttonClickChangeText"
android:layout_width="239dp"
android:layout_height="51dp"
android:gravity="clip_vertical"
android:layout_marginTop="564dp"
android:layout_marginLeft="100dp"
android:text="Calc"
android:visibility="visible"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<EditText
android:id="@+id/datePickedText"
android:gravity="center_vertical"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="50dp"
android:layout_marginLeft="100dp"
android:layout_marginEnd="0dp"
android:ems="5"
android:enabled="true"
android:inputType="date"
android:layout_gravity="center"
android:text="dd-mm-yyyy"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</FrameLayout>
<fragment
android:layout_width="match_parent"
android:layout_height="0dp"
android:id="@+id/navHostFragment"
android:name="androidx.navigation.fragment.NavHostFragment"
app:layout_constraintTop_toBottomOf="@+id/action_bar"
app:layout_constraintBottom_toBottomOf="parent"
app:defaultNavHost="true"
app:startDestination="@layout/_main_fragment"
app:navGraph="@navigation/main_navigation">
and main_navigation has the following code
<?xml version="1.0" encoding="utf-8"?>
<navigation 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/main_navigation">
<fragment
android:id="@+id/mainFragment"
tools:layout="@layout/_main_fragment"
android:name="com.example.firstapplication.main_fragment" android:label="_main_fragment">
</fragment>
<fragment
android:id="@+id/profileFragment"
tools:layout="@layout/_profile_fragment"
android:name="com.example.firstapplication.profile_fragment" android:label="_profile_fragment">
</fragment>
<fragment
android:id="@+id/notificationFragment"
tools:layout="@layout/_notification_fragment"
android:name="com.example.firstapplication.profile_fragment" android:label="_notification_fragment">
</fragment>
<fragment
android:id="@+id/settingsFragment"
tools:layout="@layout/_settings_fragment"
android:name="com.example.firstapplication.profile_fragment" android:label="@string/hello_settings_fragment">
</fragment>
</navigation>
and MainActivity
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
try{
var navController: NavController = navigationsidemenu.findNavController()
var navigationsidemenu: NavigationView =findViewById(R.id.navigationsidemenu)
NavigationUI.setupWithNavController(navigationsidemenu,navController)
}catch(Ex:Exception)
{
println(Ex.message)
print(Ex.localizedMessage)
}
}
So I wonder wha I could I be doing possibly wrong?
Thank you and I really appreaciate helping me with this as I am novice in kotlin
Solution 1:
Where is your start destination in you main_navigation.xml?
add this app:startDestination="@id/yourStartDestinationFragmentId" to Your main_navigation.xml
<?xml version="1.0" encoding="utf-8"?>
<navigation 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"
app:startDestination="@id/yourStartDestinationFragmentId"
android:id="@+id/main_navigation">