标签: jetpack-compose-navigation

Jetpack Compose 导航 - 底部导航多个返回堆栈 - 查看模型范围问题

所以我有两个选项卡,选项卡 A 和选项卡 B。每个选项卡都有自己的后堆栈。我使用此谷歌文档中的代码实现了多个返回堆栈导航

    val navController = rememberNavController()
Scaffold(
  bottomBar = {
    BottomNavigation {
      val navBackStackEntry by navController.currentBackStackEntryAsState()
      val currentDestination = navBackStackEntry?.destination
      items.forEach { screen ->
        BottomNavigationItem(
          icon = { Icon(Icons.Filled.Favorite, contentDescription = null) },
          label = { Text(stringResource(screen.resourceId)) },
          selected = currentDestination?.hierarchy?.any { it.route == screen.route } == true,
          onClick = {
            navController.navigate(screen.route) {
              // Pop up to the start destination of the graph to
              // avoid building up a large stack of destinations
              // on the …
Run Code Online (Sandbox Code Playgroud)

android kotlin android-jetpack-navigation android-jetpack-compose jetpack-compose-navigation

5
推荐指数
1
解决办法
5420
查看次数

来自 Oauth 的 Jetpack Compose Deeplink 导航

我正在尝试通过 ViewModel 中的codeGitHub Oauth API获取. 我的可组合屏幕配置:playground://gh?code=XYZsavedStateHandler

NavGraphBuilder.composable(
         route = "login",
         deepLinks = listOf(navDeepLink {
            uriPattern = "playground://gh?code={code}"
         })
      ) {
         Log.d("MyLog", it.arguments?.getString("code", "nothing") ?: "null")
         //...
      }
Run Code Online (Sandbox Code Playgroud)

MyLog总是nothing

我也尝试实现该NavGraphBuilder.composable.arguments参数,但结果是一样的。

我刚刚熟悉 Compose 并完成了 Google Code 实验室。https://developer.android.com/codelabs/jetpack-compose-navigation#4 - 这按预期工作,但问题是需要参数。

我还有一个需要 URL 并且可以工作的 WebViewScreen 可组合项。

builder.composable(
         route = "browser",
         arguments = listOf(
            navArgument("url") {
               type = NavType.StringType
            }
         ),
         deepLinks = listOf(
            navDeepLink {
               uriPattern = "playground://gh/browser/{url}"
            }
         )
      ) {
         //...
      }
Run Code Online (Sandbox Code Playgroud)

不确定这是否可以通过 …

android android-jetpack-compose jetpack-compose-navigation

5
推荐指数
1
解决办法
1409
查看次数

Jetpack Compose 导航状态无法恢复

我正在努力使用 Jetpack Compose 导航。我遵循 NowInAndroid 架构,但没有正确的行为。我的底部栏中有 4 个目的地,其中之一是 Feed 类型的目的地。在本例中,它调用 Firebase 数据库来获取多个产品。问题是,每次我更改目标(ej -> SearchScreen)并返回到 Feed 时,该(Feed)都不会恢复并再次加载所有数据。有人知道发生了什么事吗?

这是我的 navigationTo 函数 ->

fun navigateToBottomBarRoute(route: String) {
    val topLevelOptions = navOptions {
        popUpTo(navController.graph.findStartDestination().id) {
            saveState = true
        }
        launchSingleTop = true
        restoreState = true
    }
    when (route) {
        HomeSections.FEED.route -> navController.navigateToFeed(navOptions = topLevelOptions)
        HomeSections.SEARCH.route -> navController.navigateToSearch(navOptions = topLevelOptions)
        else -> {}
    }
}
Run Code Online (Sandbox Code Playgroud)

我的提要屏幕 ->

@OptIn(ExperimentalLifecycleComposeApi::class)
@Composable
fun Feed(
    onProductClick: (Long, String) -> Unit,
    onNavigateTo: (String) -> Unit,
    modifier: Modifier = Modifier,
    viewModel: …
Run Code Online (Sandbox Code Playgroud)

android kotlin android-jetpack-compose kotlin-stateflow jetpack-compose-navigation

5
推荐指数
0
解决办法
544
查看次数

Jetpack Compose,使用 NavHost 导航时可变状态会导致无限重组

这是导致无限重组问题的代码

主要活动

class MainActivity : ComponentActivity() {
    
     override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        
        setContent {
                val navController = rememberNavController()
                val viewModel : MainViewModel by viewModel()
                val state by viewModel.state.observeAsState()

                NavHost(navController = navController, startDestination = "firstScreen") {
                    composable("firstScreen") { FirstScreen(
                        navigate = {
                        navController.navigate("secondScreen")
                    }, updateState = {
                            viewModel.getState()
                       },
                       state

                    )}

                    composable("secondScreen") { SecondScreen() }
                }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

视图模型

class MainViewModel : ViewModel() {

    //var state = MutableStateFlow(0)

    private val _state = MutableLiveData(0)
    val state: LiveData<Int> = _state

    fun …
Run Code Online (Sandbox Code Playgroud)

android kotlin android-jetpack-compose jetpack-compose-navigation compose-recomposition

5
推荐指数
1
解决办法
1781
查看次数

您是否可以通过从密封类调用字符串资源来获取字符串资源的实际值?

我想在顶部栏中向我的应用程序添加一个字符串资源,但是当我调用它时会出现一个数字,并且因为它是一个密封类,所以它不允许我实现stringResourcegetString

<resources>
    <string name="app_name">AppEsquema</string>
    <string name="app"><b>"Translator</b>"</string>
</resources>
Run Code Online (Sandbox Code Playgroud)
sealed class Destinations(
    val route: String,
    val title: String,
    val icon: ImageVector
){
    //Bottom bar windows
    object Translate: Destinations(R.string.app.toString(), "Translate", Icons.Default.Translate)
    object Words: Destinations("Words", "Words", Icons.Default.Assignment)
    object Numbers: Destinations("Numbers", "Numbers", Icons.Default.FormatListNumbered)
}
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述

我不直接输入字符串,因为顶部栏在浏览窗口时会更改名称,并且我希望它能够个性化。

这是通过窗口更改标题的代码,如果它有效,但它获取窗口路径的名称,我看到的唯一解决方案是将字符串资源分配给路径来自定义它。

在此输入图像描述

resources android kotlin android-jetpack-compose jetpack-compose-navigation

5
推荐指数
1
解决办法
387
查看次数

Jetpack Compose - 如何识别用户正在通过后退导航访问

我遇到了这样的要求:当用户通过后退导航流程返回时,我必须执行某些任务。

假设:当前用户位于 A 屏幕上,单击按钮后导航到 B 屏幕。在 B 屏幕上,我正在BackHandler使用此代码将用户导航到后屏幕,navController.navigateUp()因为此代码可以完美地将用户导航到后屏幕。

但我无法确定用户是通过后退导航还是初始启动流程来的。

已经尝试过的解决方案: val isFromBackNavigation = parentNavController.currentBackStackEntryAsState().value?.destination?.route == AppNav.Wishlist.route 对于初始启动,这也会返回 true。

android android-jetpack-compose jetpack-compose-navigation

5
推荐指数
0
解决办法
1461
查看次数

ViewModel 使用 JetpackCompose 触发导航

在 Android 中,我经常想要导航以响应 ViewModel 的状态更改。(例如,成功的身份验证会触发导航到用户的主屏幕。)

最佳实践是从 ViewModel 内触发导航吗?是否有有意的机制来触发可组合项中的导航以响应 ViewModel 状态更改?

使用 Jetpack Compose 处理此用例的过程并不明显。如果我尝试类似以下示例的操作,将会发生导航,但我导航到的目的地将无法正常运行。我相信这是因为在调用导航之前不允许完成原始的可组合函数。

// Does not behave correctly.
@Composable fun AuthScreen() {
    val screenState = viewModel.screenState.observeAsState()
    if(screenState.value is ScreenState.UserAuthenticated){
        navController.navigate("/gameScreen")
    } else {
        LoginScreen()
    }
}
Run Code Online (Sandbox Code Playgroud)

如果我使用 LaunchedEffect ,我确实会观察到正确的行为,如下所示:

// Does behave correctly.
@Composable fun AuthScreen() {
    val screenState = viewModel.screenState.observeAsState()
    if(screenState.value is ScreenState.UserAuthenticated){
        LaunchedEffect(key1 = "test") {
            navController.navigate("$/gameScreen")
        }
    } else {
        LoginScreen()
    }
}
Run Code Online (Sandbox Code Playgroud)

它是否正确?LaunchedEffect 的文档说明如下,但我并不是 100% 清楚其含义:

当 LaunchedEffect 进入组合时,它将启动块到组合的 CoroutineContext 中。当 LaunchedEffect 用不同的 key1、key2 或 …

android android-jetpack-compose jetpack-compose-navigation compose-recomposition

5
推荐指数
1
解决办法
1319
查看次数

使用 hilt 将 Activity 中的视图模型共享到 compose 函数

我的应用程序使用 hilt,我LoadManager在活动内部进行了一些工作,使用读取联系人ContentResolver,当我完成工作时,我得到发送到我的 viewModel 的光标,以便处理数据并执行一些业务逻辑,为此我声明了以下内容在我的活动之上:

@AndroidEntryPoint
class MainActivity : ComponentActivity(), LoaderManager.LoaderCallbacks<Cursor> {
    private val contactsViewModel: ContactsViewModel by viewModels()
 ...
Run Code Online (Sandbox Code Playgroud)

这样我就可以在里面使用它onLoadFinished

    override fun onLoadFinished(loader: Loader<Cursor>, cursor: Cursor?) {
  
                contactsViewModel.updateContactsListFromCursor(cursor, loader.id)
     }

Run Code Online (Sandbox Code Playgroud)

在我的 viewModel 中,我有以下代码,它使用要显示的联系人更新列表的 ui 状态:

data class ContactsListUiState(
    val contacts: MutableList<Contact>,
    val searchFilter: String)

@HiltViewModel
class ContactsViewModel @Inject constructor() : ViewModel() {
    private val _contactsListUiState =
        MutableStateFlow(ContactsListUiState(mutableStateListOf(), ""))
    val contactsListUiState: StateFlow<ContactsListUiState> = _contactsListUiState.asStateFlow()

    private fun updateContactsList(filter: String) {
        viewModelScope.launch(Dispatchers.IO) {
            ...

            _contactsListUiState.update { currentState -> …
Run Code Online (Sandbox Code Playgroud)

android android-viewmodel android-jetpack-compose dagger-hilt jetpack-compose-navigation

5
推荐指数
1
解决办法
2814
查看次数

如何避免 onClick 回调被多次调用 Jetpack Compose

在测试我的应用程序时,我意识到如果用户FloatingActionButton快速按下几次,onClick 回调可能会被多次触发。就我而言,这导致返回堆栈被多次弹出,因为onPopBackStack回调会冒泡到NavHost它可以访问navController并调用该popBackStack方法的位置。

fun AddEditTodoScreen(onPopBackStack: () -> Unit, viewModel: AddEditTodoViewModel = viewModel()) {

    var isNavigating by remember{
        mutableStateOf(false)
    }

    LaunchedEffect(key1 = true){
        viewModel.uiEvent.collect{event : UiEvent ->
            when(event){
                is UiEvent.PopBackStack -> onPopBackStack
                else -> Unit
            }
        }
    }

    Scaffold(floatingActionButton = {
        FloatingActionButton(onClick = {
            if(!isNavigating){
                isNavigating = !isNavigating
                onPopBackStack()
            }
        }) {
            Icon(imageVector = Icons.Default.Check, contentDescription = "Check")
        }
Run Code Online (Sandbox Code Playgroud)

目前,我只是在第一次单击isNavigating时将 a 设置为 true FloatingActionButton,如果再次单击,它会检查该isNavigating标志是否设置为 true,如果是,则不执行任何操作。如果有的话,有什么更好的方法来解决这个问题?

android android-jetpack-compose jetpack-compose-navigation

5
推荐指数
1
解决办法
1754
查看次数

如何在 Android jetpack 组成单一活动应用程序中从通知导航到特定屏幕?

我想从通知操作按钮导航到撰写中的单个活动应用程序中的特定屏幕。根据此文档,我决定使用深层链接导航。问题是,当我单击通知操作按钮时,它会在导航到预期屏幕之前重新启动我的活动。如果我的活动在后台打开,我不希望它重新启动。

我就是这样做的:

清单.xml

这是我在应用程序清单中指定的内容:

<activity
    android:name=".ui.AppActivity"
    android:launchMode="standard"
    android:exported="true">
    <intent-filter>
         <action android:name="android.intent.action.MAIN" />
         <category android:name="android.intent.category.LAUNCHER" />
    </intent-filter>
    <intent-filter>
         <action android:name="android.intent.action.VIEW" />
         <category android:name="android.intent.category.DEFAULT" />
         <category android:name="android.intent.category.BROWSABLE" />
         <data android:scheme="myApp" android:host="screenRoute" />
    </intent-filter>
</activity>
Run Code Online (Sandbox Code Playgroud)

根导航图

这是我的根导航图中的深层链接声明:

composable(
   route = "screenRoute",
   deepLinks = listOf(navDeepLink { uriPattern = "myApp://screenRoute" })
) {
   ComposableScreen()
}
Run Code Online (Sandbox Code Playgroud)

待定意向

这是我用于通知操作按钮的待处理意图:

val intent = Intent().apply {
    action = Intent.ACTION_VIEW
    data = "myApp://screenRoute".toUri()
}

val deepLinkPendingIntent = TaskStackBuilder.create(context).run {
    addNextIntentWithParentStack(intent)
    getPendingIntent(1234, FLAG_UPDATE_CURRENT)
}
Run Code Online (Sandbox Code Playgroud)

我以为我在这里做错了什么,因为我没有找到任何关于这次重启的信息。因此,我下载了使用深层链接的官方撰写导航代码实验室(因为它也是单个应用程序活动),并且在使用来自意图的深层链接时执行相同的操作,活动将重新启动。

所以我的问题是:

  1. 是否可以在单个活动应用程序中从通知实现深层链接导航而无需重新启动它? …

android-jetpack-compose jetpack-compose-navigation

5
推荐指数
1
解决办法
2589
查看次数