.opencode/skills/jetpack-compose-safe-areas/SKILL.md
Correct handling of safe areas in Jetpack Compose Android applications. Use when working with TopAppBar, Scaffold, and screen safe areas in Jetpack-WorkoutApp.
npx skillsauth add easydev991/Jetpack-WorkoutApp jetpack-compose-safe-areasInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
In Jetpack Compose, the TopAppBar component automatically handles safe areas (status bar insets) and requires no additional configuration. This means that with proper implementation, the screen header will not be overlapped by camera, speaker, or other system elements on devices with screen notch.
Key rule: NEVER use windowInsets = WindowInsets(top = 0) in TopAppBar. This disables automatic safe area handling and causes content overlap.
In MainActivity, enableEdgeToEdge() is used, which forces the app to occupy the entire screen, including areas under system bars. This requires special inset configuration at the Scaffold level.
In the root screen of the application (RootScreen), a Scaffold with BottomNavigationBar is used. It is important to disable automatic content padding through contentWindowInsets = WindowInsets(0, 0, 0, 0) so content does not receive extra padding. The paddingValues parameter is only used to account for BottomNavigationBar.
Rules:
contentWindowInsets = WindowInsets(0, 0, 0, 0)paddingValues parameter is only applied to NavHost to account for BottomNavigationBarUse this pattern for screens with scrolling content and optional bottom button:
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun ExampleScreen(
modifier: Modifier = Modifier,
viewModel: IExampleViewModel,
onAction: (ExampleNavigationAction) -> Unit
) {
val uiState by viewModel.uiState.collectAsState()
val scrollState = rememberScrollState()
Scaffold(
topBar = {
CenterAlignedTopAppBar(
title = { Text(text = stringResource(R.string.title)) },
navigationIcon = {
IconButton(onClick = { onAction(ExampleNavigationAction.Back) }) {
Icon(
imageVector = AutoMirroredIcons.ArrowBack,
contentDescription = stringResource(R.string.back)
)
}
}
)
},
bottomBar = {
// Optional bottom button
SaveButton(
enabled = uiState.canSave && !uiState.isLoading,
onClick = viewModel::onSaveClick
)
},
modifier = modifier
) { paddingValues ->
Box(modifier = Modifier.fillMaxSize()) {
Column(
modifier = Modifier
.fillMaxSize()
.padding(paddingValues)
.verticalScroll(scrollState)
.padding(
horizontal = dimensionResource(R.dimen.spacing_regular),
vertical = dimensionResource(R.dimen.spacing_regular)
),
verticalArrangement = Arrangement.spacedBy(dimensionResource(R.dimen.spacing_regular))
) {
// Screen content
}
// Loading overlay
if (uiState.isLoading) {
LoadingOverlayView()
}
}
}
}
paddingValues through .padding(paddingValues) modifierbottomBar slotimport androidx.compose.foundation.layout.WindowInsets
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.systemBars
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.ui.res.dimensionResource
import androidx.compose.material3.Scaffold
import androidx.compose.material3.CenterAlignedTopAppBar
Problem: Using windowInsets = WindowInsets(top = 0) disables automatic safe area handling.
Solution: Do not specify the windowInsets parameter in TopAppBar.
Problem: Content goes under TopAppBar or BottomBar.
Solution: Always apply paddingValues to the content Column: Modifier.fillMaxSize().padding(paddingValues)
Problem: Loading overlay cannot be displayed on top of scrollable content.
Solution: Wrap the content Column in a Box and place the loading overlay inside the Box after the Column.
windowInsets = WindowInsets(top = 0)contentWindowInsets = WindowInsets(0, 0, 0, 0)Modifier.fillMaxSize().padding(paddingValues)bottomBar slotverticalScroll is applied to Column, not to BoxFor full verification of correct safe area handling:
See for correct implementation:
EditProfileScreen.kt - Screen with TopAppBar, bottomBar, loading overlayEventFormScreen.kt - Screen with TopAppBar, bottomBar, loading overlayJetpack Compose documentation: https://developer.android.com/jetpack/compose/layouts/insets
testing
Пиши тесты в андроид-проекте правильно. Используй этот навык при написании любых типов тестов (unit, integration, UI), тестировании бизнес-логики, сетевых функций и компонентов UI.
tools
Реализуй pull-to-refresh в Jetpack Compose с использованием Material 3 PullToRefreshBox. Используй этот навык при добавлении возможности обновления данных на экранах со списками или карточками.
tools
Правильно работай с локализацией в Android-проекте. Используй этот навык при добавлении новых строковых ресурсов, работе с plurals, форматировании дат и текстов.
tools
Блокировка UI контента экрана во время загрузки данных или выполнения асинхронных операций с отображением индикатора загрузки. Используй этот навык при разработке экранов с сетевыми запросами, операциями CRUD и других асинхронных действий.