ワンクリックで
edge-to-edge
Edge-to-edge and window-inset handling for Compose screens, scaffolds, sheets, and system bars.
Codex または Claude でインストール この Prompt をコピーして Codex、Claude、または他のアシスタントに貼り付けると、Skill ページを確認してインストールできます。
メニュー
Edge-to-edge and window-inset handling for Compose screens, scaffolds, sheets, and system bars.
Codex または Claude でインストール この Prompt をコピーして Codex、Claude、または他のアシスタントに貼り付けると、Skill ページを確認してインストールできます。
SOC 職業分類に基づく
Use this skill to generate well-branded interfaces and assets for RIPDPI (an Android-native, Compose-first VPN and DPI-bypass app), either for production or throwaway prototypes/mocks/etc. Contains essential design guidelines, colors, type, fonts, brand-ship icons, and an interactive UI kit of every public composable from the live ui/components tree.
Use when managing the Rust workspace, adding/removing crates, editing workspace dependencies, running cargo nextest/audit/deny, configuring Cargo profiles for Android cross-compilation, debugging Cargo.lock churn, migrating crate edition, or wiring Gradle to cargo via the ripdpi.android.rust-native plugin.
Use when modifying the diagnostics scan pipeline, ScanRequest/ScanReport types, ProbeTask families, ripdpi-monitor-engine / ripdpi-diagnostics-* crates, strategy-probe candidates, the diagnostics catalog (packs/profiles), wire-schema contracts between Rust and Kotlin, DIAGNOSTICS_ENGINE_SCHEMA_VERSION, golden contract tests, or adding a new probe type / profile. Triggers on diagnostics scans, strategy probes, automatic audit, dpi-detector profiles, or anything in core/diagnostics or native/rust/crates/ripdpi-monitor-*.
Android-specific Rust build, verification, and packaging — per-target 16 KiB page alignment, size-optimized release profile, ELF symbol allowlist, .so size budgets, NDK 29 specifics. Use when modifying .cargo/config.toml for Android targets, the workspace [profile.release] / [profile.android-jni] block, or when verifying a built .so before release.
Telemetry and observability discipline for the RIPDPI Android Rust stack — control-plane vs data-plane logging, bounded flume event queues, atomic counters, snapshot polling, readiness callbacks, and deterministic JSON contracts. Use when authoring or modifying telemetry emission code, the bounded event ring, the Kotlin-side telemetry consumer, or any per-packet logging.
Custom detekt rules, DI/privacy/suppression guardrails, detekt.yml configuration, and false-positive triage.
| name | edge-to-edge |
| description | Edge-to-edge and window-inset handling for Compose screens, scaffolds, sheets, and system bars. |
Read ripdpi.targetSdk and ripdpi.compileSdk from gradle.properties before auditing. When the live target is API 35 or newer, Android 15+ enforces edge-to-edge regardless of theme flags — any screen that wraps content without inset handling will clip under the status or navigation bars.
app/src/main/kotlin/com/poyka/ripdpi/activities/MainActivity.kt is the only call site; locate onCreate by symbol rather than retaining a line-number snapshot:
override fun onCreate(savedInstanceState: Bundle?) {
val splashScreen = installSplashScreen()
enableEdgeToEdge()
super.onCreate(savedInstanceState)
...
}
Rule: installSplashScreen() must run before enableEdgeToEdge(), and both must run before super.onCreate(...). Read the active splashscreen version from gradle/libs.versions.toml; the splash overlay lifecycle must attach before the activity window switches to edge-to-edge mode.
Do not call enableEdgeToEdge() from a second activity, a Compose entry, or a @Composable effect. The activity owns the window.
For any composable that touches a screen edge, you must pick one inset source:
| Inset | When to use | Notes |
|---|---|---|
WindowInsets.safeDrawing | Default for most content surfaces. Union of system bars + display cutout + IME. | What you want unless you have a specific reason otherwise. |
WindowInsets.systemBars | Only the status + navigation bars. Use when you explicitly want to draw under a display cutout. | Rare in RIPDPI; status bar is the common case. |
WindowInsets.navigationBars | Bottom nav only. Use for a custom bottom bar that should sit above the system nav gesture area. | See BottomNavBar.kt for the anchor. |
WindowInsets.statusBars | Top system bar only. Rare — prefer safeDrawing so cutouts are handled. | Use when you want to draw behind the status bar but respect the nav bar normally. |
WindowInsets.ime | Keyboard insets. | Combine with others via union() for fields that must stay above the keyboard. |
windowInsetsPadding vs safeDrawingPaddingModifier.windowInsetsPadding(WindowInsets.navigationBars) // only nav bar
Modifier.safeDrawingPadding() // safeDrawing shortcut
safeDrawingPadding() is the convenience modifier for windowInsetsPadding(WindowInsets.safeDrawing). Prefer it on root containers. Use windowInsetsPadding(...) with an explicit inset source only when you need a specific subset (e.g. a bottom bar that handles just the nav bar, so the status bar is handled by the content above it).
Do not stack padding modifiers that apply overlapping insets — safeDrawingPadding() + windowInsetsPadding(WindowInsets.statusBars) double-pads the top. One modifier per axis, and let the composable tree handle the rest via consumeWindowInsets.
RipDpiBottomSheet.kt and BottomNavBar.kt are the two bottom-edge anchor files. When authoring a new bottom sheet or modifying an existing one:
WindowInsets.navigationBarsIgnoringVisibility for bottom sheets that must remain fixed even when the gesture nav pill transiently hides. This is the difference between a nav bar that briefly disappears during scroll and a sheet that jumps 24dp.WindowInsets.ime.union(WindowInsets.navigationBars) on the sheet container ensures fields remain visible above the keyboard on devices where the IME doesn't fully overlap the nav bar.Material 3 Scaffold handles insets for its own top bar, bottom bar, and FAB slots. Read the active Compose BOM from gradle/libs.versions.toml before making version-specific claims. If you put a custom bar outside a Scaffold slot and provide a topBar or bottomBar at the same time, you are inset-padding twice. Pick one:
Scaffold slots and let it handle insets → don't add padding modifiers to the slot content.Scaffold slots and handle insets manually on your custom bars.Mixing produces the classic "my bottom bar sits 48dp too high" regression.
The splashscreen library keeps the splash visible until setKeepOnScreenCondition { ... } returns false. In MainActivity.onCreate, locate the current condition and verify that it follows viewModel.startupState.value.isReady; do not rely on a stored line number. The splash overlay sits on top of the activity window, so edge-to-edge enforcement on MainActivityContent does not affect what the user sees during splash.
Gotcha: if you ever migrate away from installSplashScreen() to a custom splash composable, you must add inset handling to the custom composable yourself — it no longer has the splash library's overlay to hide behind.
After any edge-to-edge change:
maestro/03-advanced-settings-edit-save.yaml as a spot check for form-field insets.app/src/test must be re-recorded if inset padding on a visible surface changed: ./gradlew recordScreenshots then review the diff.docs/design-system.md) owns theming; edge-to-edge is about inset math, not color.minSdk = 27 means the app runs on older OSes, but R-era inset APIs are the baseline; earlier system-ui-visibility flags are not used and must not be introduced.FLAG_LAYOUT_NO_LIMITS, SOFT_INPUT_ADJUST_*). These are legacy and must not be added; modern edge-to-edge uses the Compose inset system exclusively.Run android skills edge-to-edge for Google's generic edge-to-edge skill covering API surface background, cross-version inset compat, and the View-system equivalents. Use it alongside this RIPDPI-specific skill for context on why the API shape looks the way it does. This skill is the project-specific authority for where and how to apply insets in RIPDPI's Compose tree.