2023年3月16日木曜日

Compose の LottieAnimation でクリックしたときにアニメーションさせる

rememberLottieAnimatable を使います。
  1. @Preview  
  2. @Composable  
  3. fun LottieAnimationSample() {  
  4.     val composition by rememberLottieComposition(  
  5.         LottieCompositionSpec.RawRes(R.raw.lottie_animation)  
  6.     )  
  7.     val lottieAnimatable = rememberLottieAnimatable()  
  8.     val coroutineScope = rememberCoroutineScope()  
  9.   
  10.     Box(  
  11.         contentAlignment = Alignment.Center,  
  12.         modifier = Modifier  
  13.             .fillMaxSize()  
  14.             .pointerInput(Unit) {  
  15.                 detectTapGestures(  
  16.                     onTap = {  
  17.                         coroutineScope.launch {  
  18.                             lottieAnimatable.animate(composition)  
  19.                         }  
  20.                     },  
  21.                 )  
  22.             }  
  23.     ) {  
  24.         LottieAnimation(  
  25.             composition = composition,  
  26.             progress = { lottieAnimatable.value },  
  27.             modifier = Modifier.size(72.dp),  
  28.         )  
  29.     }  
  30. }    

2023年3月8日水曜日

Navigation Compose の optional arguments に null を渡したいときは query parameter 自体を消さないといけない

Navigation Compose の destination に optional arguments を設定する場合、nullable = true を設定します(もしくは defaultValue を設定する)。
  1. composable(  
  2.     route = "detail?id={id}",  
  3.     arguments = listOf(  
  4.         navArgument("id") {  
  5.             type = NavType.StringType  
  6.             nullable = true  
  7.         }  
  8.     )  
  9. ) {  
この場合、NavHostController.navigate() に渡す文字列と id の値の関係は次のようになります。

destination 先での id の値
navController.navigate("detail")null
navController.navigate("detail?id=AAAAA")"AAAA"
navController.navigate("detail?id=")""
val id: String? = null
navController.navigate("detail?id=${id}")
"null"


注意しないといけないのは "detail?id=${id}" です。id 変数が null のとき、これは "detail?id=null" になり、destination 先では "null" という文字列が取得されてしまいます。

よって id 変数が null かどうかによって次のように navigate() に渡す文字列を変える必要があります。
  1. if (id == null) {  
  2.     navController.navigate("detail")  
  3. else {  
  4.     navController.navigate("detail?id=${id}")  
  5. }  


挙動確認のコード
  1. @Composable  
  2. fun NavigationSample() {  
  3.     val navController = rememberNavController()  
  4.     NavHost(  
  5.         navController = navController,  
  6.         startDestination = "home"  
  7.     ) {  
  8.         composable("home") {  
  9.             Column {  
  10.                 Text("home")  
  11.   
  12.                 Button(  
  13.                     onClick = {  
  14.                         navController.navigate("detail")  
  15.                     }  
  16.                 ) {  
  17.                     Text("detail")  
  18.                 }  
  19.   
  20.                 Button(  
  21.                     onClick = {  
  22.                         navController.navigate("detail?id=AAAAA")  
  23.                     }  
  24.                 ) {  
  25.                     Text("detail?id=AAAAA")  
  26.                 }  
  27.   
  28.                 Button(  
  29.                     onClick = {  
  30.                         navController.navigate("detail?id=")  
  31.                     }  
  32.                 ) {  
  33.                     Text("detail?id=")  
  34.                 }  
  35.     
  36.                 val id: String? = null  
  37.                 Button(  
  38.                     onClick = {  
  39.                         navController.navigate("detail?id=${id}")  
  40.                     }  
  41.                 ) {  
  42.                     Text("detail?id=${id}")  
  43.                 }  
  44.             }  
  45.         }  
  46.   
  47.         composable(  
  48.             route = "detail?id={id}",  
  49.             arguments = listOf(  
  50.                 navArgument("id") {  
  51.                     type = NavType.StringType  
  52.                     nullable = true  
  53.                 }  
  54.             )  
  55.         ) {  
  56.             Column {  
  57.                 val arguments = requireNotNull(it.arguments)  
  58.                 val id = arguments.getString("id")  
  59.                 Text(text = "detail")  
  60.                 Text(text = "id is null : ${id == null}")  
  61.             }  
  62.         }  
  63.     }  
  64. }