在 MainActivity 内的导航主机片段上调用方法
Calling method on navigation host fragment inside MainActivity
我正在开发我的第一个 Android 应用程序,我知道架构可能有点混乱。
我在 android 中使用新的 Jetpack 导航。我有一个导航抽屉,我在其中添加了一个回收站视图,用户可以从那里 select 回收站视图中的项目,并且基于该主导航主机片段应该滚动到特定位置。
我想知道如何调用与导航宿主片段关联的下方片段中的方法。我可以获得导航主机片段的句柄,但我想在该特定片段中调用自定义方法,该片段未通过导航主机片段公开,因此它给了我编译时错误。
我使用的方法如下。
val readerFragment: ReaderFragment = supportFragmentManager.findFragmentById(R.id.reader_fragment) as ReaderFragment
readerFragment.scrollToChapter(5)
此处 Reader 片段是在导航主机片段下方使用的实际片段,这会导致以下异常
com.example.quran E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.quran, PID: 7640
kotlin.TypeCastException: null cannot be cast to non-null type com.example.quran.ReaderFragment
或者如果尝试像这样直接从 nav_host_fragment 获取它
val readerFragment: ReaderFragment = nav_host_fragment as ReaderFragment
然后我得到以下异常
java.lang.ClassCastException: androidx.navigation.fragment.NavHostFragment cannot be cast to com.example.quran.ReaderFragment
有人可以帮助我如何从 MainActivity 中的 nav_host _fragment 中获取实际片段。
下面是 nav_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/reader_fragment">
<fragment
android:id="@+id/reader_fragment"
android:name="com.example.quran.ReaderFragment"
android:label="Reader"
tools:layout="@layout/reader_fragment">
</fragment>
<fragment
android:id="@+id/chapterDetailsFragment"
android:name="com.example.quran.ChapterDetailsFragment"
android:label="fragment_chapter_details"
tools:layout="@layout/fragment_chapter_details" />
</navigation>
这里是 MainActivity 的布局
<?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"
android:fitsSystemWindows="true"
tools:context=".MainActivity"
tools:openDrawer="start">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<androidx.appcompat.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/colorTopNavigation">
<TextView
android:id="@+id/toolbar_textView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:fontFamily="@font/montserratbold"
android:textColor="@color/toolbarItemColor"
android:layout_marginRight="?android:attr/actionBarSize"
android:gravity="center"
android:textSize="30dp"
android:textStyle="bold" />
</androidx.appcompat.widget.Toolbar>
<fragment
android:id="@+id/nav_host_fragment"
android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:defaultNavHost="true"
app:navGraph="@navigation/nav_graph" />
</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"
android:fitsSystemWindows="true">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/chapters_recycler_view"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</com.google.android.material.navigation.NavigationView>
</androidx.drawerlayout.widget.DrawerLayout>
问题说明
您在代码中的第一个错误:
val readerFragment: ReaderFragment = nav_host_fragment as ReaderFragment
是因为 NavHostFragment 是一个主机(即您的片段在其中),所以您不能将 NavHostFragment 转换为其他任何东西。
supportFragmentManager.findFragmentById(R.id.reader_fragment) as ReaderFragment
TypeCastException: null cannot be cast to non-null type
findFragmentById 返回 null,因为它没有找到您的片段。这是第二个错误。
解决方案
您可以稍微修改一下以获得屏幕片段:
NavHostFragment navHostFragment = supportFragmentManager.findFragmentById(R.id.nav_host);
navHostFragment.getChildFragmentManager().getFragments().get(0);
您还可以检查子片段管理器,因为您的片段是导航主机的子片段:
NavHostFragment fragment = supportFragmentManager.findFragmentById(R.id.nav_host);
MyFragment frag = (MyFragment) fragment.getChildFragmentManager().findFragmentByTag(tag);
参考:
我正在开发我的第一个 Android 应用程序,我知道架构可能有点混乱。 我在 android 中使用新的 Jetpack 导航。我有一个导航抽屉,我在其中添加了一个回收站视图,用户可以从那里 select 回收站视图中的项目,并且基于该主导航主机片段应该滚动到特定位置。
我想知道如何调用与导航宿主片段关联的下方片段中的方法。我可以获得导航主机片段的句柄,但我想在该特定片段中调用自定义方法,该片段未通过导航主机片段公开,因此它给了我编译时错误。
我使用的方法如下。
val readerFragment: ReaderFragment = supportFragmentManager.findFragmentById(R.id.reader_fragment) as ReaderFragment
readerFragment.scrollToChapter(5)
此处 Reader 片段是在导航主机片段下方使用的实际片段,这会导致以下异常
com.example.quran E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.quran, PID: 7640
kotlin.TypeCastException: null cannot be cast to non-null type com.example.quran.ReaderFragment
或者如果尝试像这样直接从 nav_host_fragment 获取它
val readerFragment: ReaderFragment = nav_host_fragment as ReaderFragment
然后我得到以下异常
java.lang.ClassCastException: androidx.navigation.fragment.NavHostFragment cannot be cast to com.example.quran.ReaderFragment
有人可以帮助我如何从 MainActivity 中的 nav_host _fragment 中获取实际片段。
下面是 nav_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/reader_fragment">
<fragment
android:id="@+id/reader_fragment"
android:name="com.example.quran.ReaderFragment"
android:label="Reader"
tools:layout="@layout/reader_fragment">
</fragment>
<fragment
android:id="@+id/chapterDetailsFragment"
android:name="com.example.quran.ChapterDetailsFragment"
android:label="fragment_chapter_details"
tools:layout="@layout/fragment_chapter_details" />
</navigation>
这里是 MainActivity 的布局
<?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"
android:fitsSystemWindows="true"
tools:context=".MainActivity"
tools:openDrawer="start">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<androidx.appcompat.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/colorTopNavigation">
<TextView
android:id="@+id/toolbar_textView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:fontFamily="@font/montserratbold"
android:textColor="@color/toolbarItemColor"
android:layout_marginRight="?android:attr/actionBarSize"
android:gravity="center"
android:textSize="30dp"
android:textStyle="bold" />
</androidx.appcompat.widget.Toolbar>
<fragment
android:id="@+id/nav_host_fragment"
android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:defaultNavHost="true"
app:navGraph="@navigation/nav_graph" />
</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"
android:fitsSystemWindows="true">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/chapters_recycler_view"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</com.google.android.material.navigation.NavigationView>
</androidx.drawerlayout.widget.DrawerLayout>
问题说明
您在代码中的第一个错误:
val readerFragment: ReaderFragment = nav_host_fragment as ReaderFragment
是因为 NavHostFragment 是一个主机(即您的片段在其中),所以您不能将 NavHostFragment 转换为其他任何东西。
supportFragmentManager.findFragmentById(R.id.reader_fragment) as ReaderFragment
TypeCastException: null cannot be cast to non-null type
findFragmentById 返回 null,因为它没有找到您的片段。这是第二个错误。
解决方案
您可以稍微修改一下以获得屏幕片段:
NavHostFragment navHostFragment = supportFragmentManager.findFragmentById(R.id.nav_host);
navHostFragment.getChildFragmentManager().getFragments().get(0);
您还可以检查子片段管理器,因为您的片段是导航主机的子片段:
NavHostFragment fragment = supportFragmentManager.findFragmentById(R.id.nav_host);
MyFragment frag = (MyFragment) fragment.getChildFragmentManager().findFragmentByTag(tag);
参考: