I have a simple app with a main activity, a fragment frag_home
, and a listfragment named ItemFragment
.
In frag_home
I have a calendarview. If the user selects a date, the action frag_homeDirections.actionFragHomeToItemFragment(mytimeinmillis)
opens the listfragment which shows the events of the selected day. The action uses the argument timeinmillis
, which holds the selected date in milliseconds.
Everything works fine. But if I want to create a two panel view and implement the listfragment into the layout of the main fragment (just by using the xml editor, choosing activity_main.xml, drag a fragment component into activity_main and choose listItem) I get the following error if I try to run my application:
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.myapplication, PID: 8401
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.myapplication/com.example.myapplication.MainActivity}: android.view.InflateException: Binary XML file line #29: Binary XML file line #29: Error inflating class fragment
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2756)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2817)
at android.app.ActivityThread.-wrap12(ActivityThread.java)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1556)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:163)
at android.app.ActivityThread.main(ActivityThread.java:6388)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:930)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:820)
Caused by: android.view.InflateException: Binary XML file line #29: Binary XML file line #29: Error inflating class fragment
Caused by: android.view.InflateException: Binary XML file line #29: Error inflating class fragment
Caused by: java.lang.IllegalArgumentException: navigation destination com.example.myapplication:id/destination_home is not a direct child of this NavGraph
this is my main activity in which I have implemented the fragment ItemFragment
?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_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".MainActivity" >
<androidx.appcompat.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?attr/colorPrimary"
android:theme="?attr/actionBarTheme"
/>
<com.google.android.material.bottomnavigation.BottomNavigationView
android:id="@+id/bottom_nav"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:menu="@menu/menu_navigation"/>
<fragment
android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="423dp"
android:layout_height="320dp" app:navGraph="@navigation/nav_graph" app:defaultNavHost="true"
android:id="@+id/nav_host_fragment"/>
<fragment
android:layout_width="match_parent"
android:layout_height="301dp" android:name="com.example.myapplication.ItemFragment"
android:id="@+id/fragment"/>
</LinearLayout>
<com.google.android.material.navigation.NavigationView
android:id="@+id/nav_view"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="start"
app:menu="@menu/menu_navigation"/>
</androidx.drawerlayout.widget.DrawerLayout >
this is my navigation graph
?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/nav_graph"
app:startDestination="@+id/frag_home">
<fragment android:id="@+id/itemFragment" android:name="com.example.myapplication.ItemFragment"
android:label="ItemFragment" tools:layout="@layout/fragment_item">
<argument android:name="timeinmillis" app:argType="long" />
</fragment>
<fragment android:id="@+id/frag_home" android:name="com.example.myapplication.frag_home"
android:label="fragment_main" tools:layout="@layout/frag_home">
<action android:id="@+id/action_frag_home_to_itemFragment" app:destination="@id/itemFragment"/>
<action android:id="@+id/action_frag_home_to_create_Event" app:destination="@id/create_Event"/>
</fragment>
<fragment android:id="@+id/create_Event" android:name="com.example.myapplication.Create_Event"
android:label="fragment_create__event" tools:layout="@layout/fragment_create__event"/>
</navigation>
my mainActivity
class MainActivity : AppCompatActivity() {
private lateinit var linearLayoutManager: LinearLayoutManager
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
//linearLayoutManager = LinearLayoutManager(this)
//list2_recycler_view.layoutManager = linearLayoutManager
setSupportActionBar(toolbar)
val navController = Navigation.findNavController(this,R.id.nav_host_fragment)
setupBottomNavMenu(navController)
setupActionBar(navController)
setupSideNavigationMenu(navController)
}
my home fragment:
class frag_home : Fragment() {
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.frag_home, container, false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
btnCreateEvent.setOnClickListener{
//val date = "heute"
val action = frag_homeDirections.actionFragHomeToCreateEvent()
val openHandler = My_Clients_OpenHandler()
val selected_date = Calendar.getInstance().timeInMillis
// action.setStrDatum("Bussi!")
Navigation.findNavController(it).navigate(action)
}
btnListe.setOnClickListener{
//val date = "heute"
val caltmp = Calendar.getInstance()
val mytimeinmillis = caltmp.timeInMillis
val action = frag_homeDirections.actionFragHomeToItemFragment(mytimeinmillis)
val openHandler = My_Clients_OpenHandler()
// action.setStrDatum("Bussi!")
Navigation.findNavController(it).navigate(action)
}
calendarView?.setOnDateChangeListener { view, year, month, dayOfMonth ->
// Note that months are indexed from 0. So, 0 means January, 1 means february, 2 means march etc.
val selected_date = "Selected date is " + dayOfMonth + "/" + (month + 1) + "/" + year
val caltmp = Calendar.getInstance()
//val newdatetime = DateTime(year,month, dayOfMonth)
caltmp.set(year,month,dayOfMonth)
val mytimeinmillis = caltmp.timeInMillis
val sdf = SimpleDateFormat("dd.MM.yyyy HH:mm")
val strSelectedDate = sdf.format(caltmp.getTime())
val action = frag_homeDirections.actionFragHomeToItemFragment(mytimeinmillis)
view.findNavController().navigate(action)
// actionCreateEvent.setStrDatum(msg)
// Navigation.findNavController(view).navigate(actionCreateEvent)
}
}
}
and if you need the important part of itemfragment
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
arguments?.let {
columnCount = it.getInt(ARG_COLUMN_COUNT)
}
}
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
val view = inflater.inflate(
R.layout.fragment_recyclerview,
container,
false
)
//val timeinmillis = arguments?.let { ItemFragmentArgs.fromBundle(it).timeinmillis }
// val selecteddate = ItemFragmentArgs.fromBundle(arguments)
//getActivity()?.setTitle(selecteddate);
// Set the adapter
var linearLayoutManager: LinearLayoutManager
openCalendar = OpenCalendarHandler(activity)
val caltemp = Calendar.getInstance();
val longTimeinMillis = arguments?.let { ItemFragmentArgs.fromBundle(it).timeinmillis }
caltemp.timeInMillis = longTimeinMillis!!
val heute = caltemp.timeInMillis
val intCalendarId = openCalendar.getCalendarIdbyCalendarName(view.context, "Klienten_Rolandcloud")
val strCalendarId = intCalendarId!!.toString()
// alle events vom aktuell im Kalendar_Monat ausgew�hlten Tag
val selection = ("((" + CalendarContract.Events.DTSTART + " >= ?) AND ("
+ CalendarContract.Events.DTEND + " <= ?) AND ("
+ CalendarContract.Events.DELETED + " = ?) AND ("
+ CalendarContract.Events.CALENDAR_ID + " = ?))")
val t = Time()
t.set(caltemp.getTimeInMillis())
// Ende des Tages indem ich die Uhrzeit auf 23:59 und 59 Sekunden
// stelle..
t.set(59, 59, 23, t.monthDay, t.month, t.year)
val dtEnd = java.lang.Long.toString(t.toMillis(false))
val strEnde = openCalendar.getStringTimeinMillis(
t.toMillis(false),
"yyyy-MM-dd HH:mm"
)
// Start des Tages bei 00:00
t.set(0, 0, 0, t.monthDay, t.month, t.year)
val strStart = openCalendar.getStringTimeinMillis(
t.toMillis(false),
"yyyy-MM-dd HH:mm"
)
val dtStart = java.lang.Long.toString(t.toMillis(false))
val selectionArgs = arrayOf(dtStart, dtEnd, "0", intCalendarId.toString())
//my_recyclerview // Add this
val activity = activity as Context
val my_recycler_view = view.findViewById<RecyclerView>(R.id.my_recycler_view)
val meinCursor = openCalendar.getEvents(view.context,selection,selectionArgs,null)
//linearLayoutManager = LinearLayoutManager(activity)
view.my_recycler_view.layoutManager = LinearLayoutManager(activity)
// set the custom adapter to the RecyclerView
view.my_recycler_view.adapter = MyCalendarAdapter_kotlin(view.context,meinCursor)
return view
}
override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState)
LoaderManager.getInstance(this).initLoader(EVENTLOADER_ID, null, this)
}
// populate the views now that the layout has been inflated
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
// RecyclerView node initialized here
my_recycler_view.apply {
// set a LinearLayoutManager to handle Android
// RecyclerView behavior
val caltmp = Calendar.getInstance()
}
}
/*
So how can I fix this error, if I want to implement the listfragment into the activity_main fragment. My goal: to see both fragments frag_home with calendarview and beyond that fragment the listfragment with the events of the day. All by using the navigation component and actions.
Or is it impossible to use the navigation component to navigate to a fragment, which is implemented in an other layout? Thanks!!
Android Jetpack's Navigation component helps you implement navigation, from simple button clicks to more complex patterns, such as app bars and the navigation drawer. The Navigation component also ensures a consistent and predictable user experience by adhering to an established set of principles.
To take full advantage of the Navigation component, your app should use multiple fragments in a single activity. However, activities can still benefit from the Navigation component. Note, however, that your app's UI must be visually broken up across several navigation graphs.
NavHostFragment provides an area within your layout for self-contained navigation to occur. NavHostFragment is intended to be used as the content area within a layout resource defining your app's chrome around it, e.g.: <androidx.drawerlayout.widget.DrawerLayout.
Make sure that you specify a starting fragment. For one reason or another I had no starting fragments and once fixed corrected the "not a direct child error".
Make sure you have that Start specified on a fragment
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With