我正在构建的应用程序使用带有路线的组合导航。挑战在于起始目的地是动态的。
这是一个最小的例子:
class MainActivity : ComponentActivity()
{
override fun onCreate(savedInstanceState: Bundle?)
{
super.onCreate(savedInstanceState)
setContent {
val navController = rememberNavController()
NavHost(
navController = navController,
startDestination = "dynamic/1", // doesn't work
// startDestination = "static", // workaround
) {
composable(
route = "dynamic/{$ARG_ID}",
arguments = listOf(navArgument(ARG_ID) { type = NavType.StringType }),
) {
val id = it.arguments?.getString(ARG_ID)
Text("dynamic route, received argument: $id!")
}
// part of the workaround
// composable(
// route = "static",
// ) {
// LaunchedEffect(this) {
// navController.navigate("dynamic/1") …Run Code Online (Sandbox Code Playgroud) android android-jetpack-navigation android-jetpack-compose android-navigation-graph
当配置发生更改并因此重新创建我的 Activity 和 Fragment 时,我的导航图作用域 ViewModel 不可用,而 Fragments 已再次创建。
看起来 Fragment 是在 navGraph 之前重新创建的。
我使用此代码从我的片段初始化我的 navGraph 范围的 ViewModel:
private val myViewModel: MyViewModel by navGraphViewModels(R.id.nav_graph_id)
Run Code Online (Sandbox Code Playgroud)
myViewModel如果我尝试在片段函数中使用onViewCreated,我会IllegalArgumentException在配置更改后得到一个。例外情况:
java.lang.IllegalArgumentException: No destination with ID <destination id> is on the NavController's back stack
Run Code Online (Sandbox Code Playgroud)
我该如何处理这个问题?
编辑1:
这是我的activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<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=".MainActivity">
<androidx.fragment.app.FragmentContainerView
android:id="@+id/main_nav_host"
android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="0dp"
android:layout_height="0dp"
app:defaultNavHost="true"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:navGraph="@navigation/main_nav_graph" />
</androidx.constraintlayout.widget.ConstraintLayout>
Run Code Online (Sandbox Code Playgroud)
这是我的 main_nav_graph.xml:
<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_nav_graph"
app:startDestination="@id/main_nav_graph_1"> …Run Code Online (Sandbox Code Playgroud) 我有两个 Fragment,一个是我图中的 home 片段。单击按钮后,用户将被导航到第二个片段。它通过将用户导航到第二个片段并显示文本来按预期工作。所以图很好。
现在我想编写一个仪器测试。
@RunWith(AndroidJUnit4::class)
class TransitionTest {
@Test
fun testNavigationToSecondFragment() {
val navController = TestNavHostController(
ApplicationProvider.getApplicationContext())
navController.setGraph(R.navigation.my_graph) <--throws exception
// the rest of my test continues here
}
}
Run Code Online (Sandbox Code Playgroud)
但是,上面显示的用于设置图形的行会引发以下异常:
IllegalStateException:必须在主线程上调用方法 addObserver。
我的环境:
fragment_version = 1.2.5 nav_version = 2.3.1 浓缩咖啡 = 3.3.0
有谁知道发生了什么以及如何解决它?
I'm following single activity approach. I have navigation toolbar, whenever i go to other screens (fragments) instead of hamburger icon i will have back arrow.
What i want to achieve is, pop my current fragment using action on pressing toolbar back arrow.
I've tried
requireActivity().getOnBackPressedDispatcher().addCallback(this, new OnBackPressedCallback(true) {
@Override
public void handleOnBackPressed() {
NavHostFragment.findNavController(EventDetailsFragment.this)
.navigate(R.id.action_nav_event_details_to_nav_home);
}
});
Run Code Online (Sandbox Code Playgroud)
But not getting the call over there, i checked by running app in debug mode.
android android-toolbar android-mvvm android-navigation-graph
我正在使用 Android Jetpack 导航组件。我有一个带有 id 的嵌套导航图,比如说嵌套图R.id.nested_graph
的第一个Fragment接收一个参数。
<navigation
android:id="@+id/nested_graph"
android:label="Nested Graph"
app:startDestination="@id/firstFragment">
<fragment
android:id="@+id/firstFragment"
android:name="...."
android:label="....">
<argument
android:name="item_id"
app:argType="integer" />
</fragment>
[...]
</navigation>
Run Code Online (Sandbox Code Playgroud)
如何使用安全 args将参数传递给嵌套图?
目前,我需要在包中手动传递参数,使用直接接收嵌套图的 id 的 API:
val args = Bundle()
args.putInt("item_id", itemId)
navController.navigate(R.id.nested_graph, args)
Run Code Online (Sandbox Code Playgroud)
我想使用安全参数,并执行以下操作:
val directions = OrigininFragmentDirections.nestedGraph(itemId)
navController.navigate(directions)
Run Code Online (Sandbox Code Playgroud)
但是在尝试时,我在构建时收到以下错误:
Too many arguments for public final fun nestedGraph(): NavDirections defined
Run Code Online (Sandbox Code Playgroud)
问题是导航图预处理正在生成工厂方法来创建没有签名中所需参数的NavDirections对象。
嵌套图的声明如下所示:
android android-navigation android-jetpack-navigation android-navigation-graph
我正在使用 Android Jetpack (2.2.0-alpha01) 的导航组件。
我希望使用嵌套在我的主 NavHostFragment 中的子 NavHostFragment,它配备了自己的子导航图。请查看以下图片了解上下文:
子导航主机在位于 MainNavHost 堆栈前端的片段中定义如下:
<fragment
android:id="@+id/childNavHostFragment"
android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:defaultNavHost="false"
app:navGraph="@navigation/child_graph" />
Run Code Online (Sandbox Code Playgroud)
在 CHILD Nav Host Fragment 前面的片段中,我尝试使用以下代码将 ViewModel 范围限定为 R.navigation.child_graph:
private val childGraphScopedViewModel: ChildGraphScopedViewModel by navGraphViewModels(R.navigation.child_graph) {
viewModelFactory
}
Run Code Online (Sandbox Code Playgroud)
访问 childGraphScopedViewModel 时,我收到错误消息崩溃:
java.lang.IllegalArgumentException: No NavGraph with ID 2131689472 is on the NavController's back stack.
Run Code Online (Sandbox Code Playgroud)
我相信懒惰的 init 调用by navGraphViewModel()是在 mainGraph 中寻找导航图。
如何访问子 navHostFragment 范围的 ViewModel?感谢您的时间。
android viewmodel kotlin android-architecture-navigation android-navigation-graph
Android 的导航组件能否用于在 BottomSheet 内导航(即在单个底部工作表中替换/添加片段)?
我知道如何BottomSheetDialogFragment使用<dialog>导航图中的标签启动一个。例如,下面的代码nav_graph.xml允许用户从一个BottomSheetDialogFragment(fragmentOne)导航到另一个BottomSheetDialogFragment(fragmentTwo)。FragmentTwo 作为第二个BottomSheet 打开,位于FragmentOne 的BottomSheet 之上。
但是,如果我想让 fragmentTwo 替换同一个 BottomSheet 中的 fragmentOne 怎么办?我将如何使用导航图完成此操作?
<navigation android:id="@+id/nav_graph"
app:startDestination="@id/fragmentOne">
<dialog android:id="@+id/fragmentOne"
android:name="com.example.navcomponentapp.FragmentOne"
android:label="fragment_fragment_one"
tools:layout="@layout/fragment_fragment_one">
<action android:id="@+id/action_fragmentOne_to_fragmentTwo2"
app:destination="@id/fragmentTwo"/>
</dialog>
<dialog android:id="@+id/fragmentTwo"
android:name="com.example.navcomponentapp.FragmentTwo"
android:label="fragment_fragment_two"
tools:layout="@layout/fragment_fragment_two"/>
</navigation>
Run Code Online (Sandbox Code Playgroud)
演示(这不是我想要的。我不想在另一个bottomSheet上打开一个bottomSheet

android android-navigation android-architecture-components android-jetpack android-navigation-graph
我有2个片段通话CreateRoomFragment和DisplayPhotoFragment,导航图是这个样子的:
<navigation>
<fragment
android:id="@+id/createRoomFragment"
android:name="package.room.CreateRoomFragment"
android:label="Create a room"
tools:layout="@layout/fragment_create_room">
<action
android:id="@+id/action_createRoomFragment_to_roomFragment"
app:destination="@id/roomFragment" />
<action
android:id="@+id/action_createRoomFragment_to_displayPhotoFragment"
app:destination="@id/displayPhotoFragment" />
</fragment>
<fragment
android:id="@+id/displayPhotoFragment"
android:name="package.fragment.DisplayPhotoFragment"
android:label="fragment_display_photo"
tools:layout="@layout/fragment_display_photo" >
<argument android:name="bitmap"
app:argType="android.graphics.Bitmap"/>
</fragment>
Run Code Online (Sandbox Code Playgroud)
所以当我想从 to 移动CreateRoomFragment时DisplayPhotoFragment,我使用如下 do:
NavDirections action = CreateRoomFragmentDirections.actionCreateRoomFragmentToDisplayPhotoFragment(selectedPhoto);
Navigation.findNavController(view).navigate(action);
Run Code Online (Sandbox Code Playgroud)
这样做,我可以导航到DisplayPhotoFragment.
但是当我按下back设备的按钮以及Back arrow工具栏中的 时,它无法返回到CreateRoomFragment。
我试过这个,但仍然无法回到上一个片段:
requireActivity().getOnBackPressedDispatcher().addCallback(getViewLifecycleOwner(),
new OnBackPressedCallback(true) {
@Override
public void handleOnBackPressed() {
navController.navigateUp(); //I tried this
navController.popBackStack(R.id.createRoomFragment,false); //and also this
}
});
Run Code Online (Sandbox Code Playgroud)
现在主要问题:
使用上面的代码,屏幕没有回到之前的Fragment( …
android android-fragments android-navigation android-architecture-navigation android-navigation-graph
当我使用 navController = Navigation.findNAvController(view) 时,我让它在活动中的标签片段中托管的片段中,应用程序因错误而崩溃:View 没有设置 navController。
这是 nav_graph:
<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/mainFragment">
<fragment
android:id="@+id/mainFragment"
android:name="studio.apptick.mouj.view.fragments.MainFragment"
tools:layout="@layout/fragment_main"
android:label="fragment_main" >
<action
android:id="@+id/action_mainFragment_to_playlistActivityFragment"
app:destination="@id/playlistActivityFragment" />
<action
android:id="@+id/action_mainFragment_to_searchActivity"
app:destination="@id/searchActivity" />
</fragment>
<activity
android:id="@+id/searchActivity"
android:name="studio.apptick.mouj.view.activity.SearchActivity"
android:label="activity_search"
tools:layout="@layout/activity_search" />
</navigation>
Run Code Online (Sandbox Code Playgroud)
这是活动中的片段标签:
android:id="@+id/nav_host_fragment"
android:layout_width="match_parent"
android:layout_height="0dp"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toTopOf="@id/view_player"
android:name="androidx.navigation.fragment.NavHostFragment"
app:defaultNavHost="true"
app:navGraph="@navigation/nav_graph">
</fragment>
Run Code Online (Sandbox Code Playgroud) navigation android navigationcontroller android-studio android-navigation-graph
我有一个简单的应用程序,其中包含一个活动和大约 4 个片段。我正在使用 android 导航组件。每次更改片段时,从我的飞溅片段开始到下一个片段, OnCreateview 和 onViewCreated 被调用两次,一次是最初创建片段时,第二次是我使用findnavController.navigate(). 我不知道为什么它会被调用两次,任何人都可以说明原因。这是我的飞溅课。
class SplashFragment : Fragment(), SocketConnection.SocketCallbacks {
lateinit var binding: SplashFragmentBinding
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
Timber.d("on View created")
SocketConnection.getInstance.socketConnectionListener(this)
}
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
Timber.d("on create view")
binding = DataBindingUtil.inflate(inflater, R.layout.fragment_splash, container, false)
return binding.root
}
override fun onResume() {
super.onResume()
Timber.d("On resume")
activity?.setupBackButton(false)
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
Timber.d("On create")
setHasOptionsMenu(false)
}
override …Run Code Online (Sandbox Code Playgroud) android android-architecture-navigation android-navigation-graph
android ×9
android-architecture-navigation ×3
kotlin ×3
android-architecture-components ×1
android-mvvm ×1
navigation ×1
viewmodel ×1