2022年8月20日土曜日

Accompanist の Navigation Material の BottomSheet で表示エリアにおさまるように配置する

Accompanist : Navigation Material @OptIn(ExperimentalMaterialNavigationApi::class) @Composable fun MyApp() { val bottomSheetNavigator = rememberBottomSheetNavigator() val navController = rememberNavController(bottomSheetNavigator) ModalBottomSheetLayout(bottomSheetNavigator) { MyNavHost(navController) } } @OptIn(ExperimentalMaterialNavigationApi::class) @Composable fun MyNavHost(navController: NavHostController) { NavHost( navController = navController, startDestination = "home" ) { composable(route = "home") { Button(onClick = { navController.navigate("sheet") }) { Text("show bottom sheet") } } bottomSheet(route = "sheet") { Box( contentAlignment = Alignment.Center, modifier = Modifier.fillMaxSize() ) { Spacer( modifier = Modifier .size(100.dp) .background(Color.Blue) ) } } } } この場合、Blue の四角は Bottom Sheet を完全に展開したときの中心に配置されます。
rememberNavController に指定した BottomSheetNavigator は NavHostController の navigatorProvider から取得できます。

BottomSheetNavigator の navigatorSheetState から BottomSheet の offset が取れるので、それを利用すると Blue の四角を BottomSheet の表示されている領域の中心に配置することができます。 @OptIn(ExperimentalMaterialNavigationApi::class) @Composable fun MyNavHost(navController: NavHostController) { NavHost( navController = navController, startDestination = "home" ) { composable(route = "home") { Button(onClick = { navController.navigate("sheet") }) { Text("show bottom sheet") } } bottomSheet(route = "sheet") { val bottomSheetNavigator = navController.navigatorProvider[BottomSheetNavigator::class] val offset = bottomSheetNavigator.navigatorSheetState.offset.value Column { Box( contentAlignment = Alignment.Center, modifier = Modifier .fillMaxWidth() .weight(1f) ) { Spacer( modifier = Modifier .size(100.dp) .background(Color.Blue) ) } with(LocalDensity.current) { Spacer(modifier = Modifier.height(offset.toDp())) } } } } }



2022年8月8日月曜日

kotlin coroutines 1.6.4 で TestScope.backgroundScope が追加された

https://github.com/Kotlin/kotlinx.coroutines/releases/tag/1.6.4

background で実行してテスト終了時にキャンセルされる coroutines を起動できます。
いままでは明示的に cancelAndJoin() していたのがいらなくなりますね。

@Test fun test() = runTest { val list = mutableListOf<SomeValue>() val job = launch(UnconfinedTestDispatcher()) { repository.someValueFlow().collect { list.add(it) } } ... assertEquals(expectedSomeValueList, list) job.cancelAndJoin() } @Test fun test() = runTest { val list = mutableListOf<SomeValue>() backgroundScope.launch(UnconfinedTestDispatcher()) { repository.someValueFlow().collect { list.add(it) } } ... assertEquals(expectedSomeValueList, list) }