SwiftUI の ZStack 相当
Jetpack Compose では Box です。
ローディングスピナーを画面全体に重ねる場合はこんな感じになります。
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
Box( modifier = Modifier.fillMaxSize() ) { MainScreen( ... ) if (isLoading) { Box( modifier = Modifier .fillMaxSize() .background(Color.Black.copy(alpha = 0.3f)), contentAlignment = Alignment.Center ) { CircularProgressIndicator() } } } |
SwiftUIでいうと
ZStack {
MainScreen()
if isLoading {
Color.black.opacity(0.3)
.ignoresSafeArea()
ProgressView()
}
}
とほぼ同じです。
ViewModelに持たせるのがおすすめ
TableDataStore に
var isLoading by mutableStateOf(false)
private set
を追加して、
suspend fun load(...) = withContext(Dispatchers.IO) {
isLoading = true
try {
...
} finally {
isLoading = false
}
}
とすると、
if (tableDataStore.isLoading) {
...
}
で簡単に表示できます。
タップも無効化したい場合
背景を半透明にしているだけだと、下の画面を押せてしまうことがあります。
完全にモーダル化するなら、
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
if (isLoading) { Box( modifier = Modifier .fillMaxSize() .background(Color.Black.copy(alpha = 0.3f)) .clickable( indication = null, interactionSource = remember { MutableInteractionSource() } ) {} ) { CircularProgressIndicator( modifier = Modifier.align(Alignment.Center) ) } } |
のようにタップを吸収させます。
個人的には今回のケースなら、AppRoot() の一番外側を
Box(
modifier = Modifier.fillMaxSize()
)
にして、
if (tableDataStore.isLoading) {
LoadingOverlay()
}
を重ねる構成が SwiftUI の ZStack + ProgressView にかなり近くて移植しやすいと思います。さらに Android らしくするなら、保存中は "暗号化中..."、読込中は "復号中..." のテキストも付けるとユーザー体験が良くなります。