maui-safe-area
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseSafe Area & Edge-to-Edge Layout (.NET 10+)
安全区域与边到边布局(.NET 10+)
.NET 10 introduces a brand-new, cross-platform safe area API that replaces the legacy iOS-only and the layout-level properties. The new property and flags enum give you per-edge, per-control safe area management on Android, iOS, and Mac Catalyst from a single API surface.
UseSafeAreaIgnoreSafeAreaSafeAreaEdgesSafeAreaRegionsThis is new API surface in .NET 10. If the project targets .NET 9 or earlier, these APIs do not exist. Guide the developer to the legacyandios:Page.UseSafeAreaproperties instead.Layout.IgnoreSafeArea
.NET 10 引入了全新的跨平台安全区域 API,替代了旧版仅适用于 iOS 的 和布局层级的 属性。全新的 属性和 标志枚举通过统一的 API 层,支持在 Android、iOS 和 Mac Catalyst 平台上实现按控件、按边缘的安全区域管理。
UseSafeAreaIgnoreSafeAreaSafeAreaEdgesSafeAreaRegions这是 .NET 10 新增的 API 层。 如果项目面向 .NET 9 或更低版本,这些 API 不存在,请引导开发者使用旧版的和ios:Page.UseSafeArea属性。Layout.IgnoreSafeArea
When to Use
适用场景
- Content overlaps status bar, notch, Dynamic Island, or home indicator after upgrading to .NET 10
- Implementing edge-to-edge / immersive layouts (photo viewers, video players, maps)
- Keyboard avoidance for chat or form UIs
- Migrating from ,
ios:Page.UseSafeArea, orLayout.IgnoreSafeAreaWindowSoftInputModeAdjust.Resize - Blazor Hybrid apps that need CSS coordination
env(safe-area-inset-*) - Mixed layouts with an edge-to-edge header but a safe-area-respecting body
- 升级到 .NET 10 后内容与状态栏、刘海屏、灵动岛或 home 指示条重叠
- 实现边到边/沉浸式布局(图片查看器、视频播放器、地图)
- 聊天或表单 UI 的键盘避让需求
- 从 、
ios:Page.UseSafeArea或Layout.IgnoreSafeArea迁移WindowSoftInputModeAdjust.Resize - 需要协调 CSS 的 Blazor Hybrid 应用
env(safe-area-inset-*) - 边到边头部 + 适配安全区域主体的混合布局
When Not to Use
不适用场景
- Projects targeting .NET 9 or earlier — use the legacy iOS-specific APIs
- General page layout questions unrelated to system bars or keyboard — use standard layout guidance
- App lifecycle or navigation structure — use maui-app-lifecycle or Shell guidance
- Theming or visual styling — use the maui-theming skill
- 面向 .NET 9 或更低版本的项目 —— 请使用旧版 iOS 专属 API
- 与系统栏或键盘无关的通用页面布局问题 —— 请参考标准布局指南
- 应用生命周期或导航结构问题 —— 请参考 maui-app-lifecycle 或 Shell 相关指南
- 主题或视觉样式问题 —— 请使用 maui-theming 技能
Inputs
输入要求
- Target framework: must be or later for the new APIs
net10.0-* - Target platforms: Android, iOS, Mac Catalyst (Windows does not have system bar insets)
- UI approach: XAML/C#, Blazor Hybrid, or MauiReactor
- 目标框架:必须为 或更高版本才可使用新 API
net10.0-* - 目标平台:Android、iOS、Mac Catalyst(Windows 没有系统栏内边距)
- UI 实现方式:XAML/C#、Blazor Hybrid 或 MauiReactor
SafeAreaRegions Enum
SafeAreaRegions 枚举
csharp
[Flags]
public enum SafeAreaRegions
{
None = 0, // Edge-to-edge — no safe area padding
SoftInput = 1 << 0, // Pad to avoid the on-screen keyboard
Container = 1 << 1, // Stay inside status bar, notch, home indicator
Default = -1, // Use the platform default for the control type
All = 1 << 15 // Respect all safe area insets (most restrictive)
}SoftInputContainerSafeAreaRegions.Container | SafeAreaRegions.SoftInputcsharp
[Flags]
public enum SafeAreaRegions
{
None = 0, // 边到边 —— 无安全区域内边距
SoftInput = 1 << 0, // 添加内边距避让屏幕键盘
Container = 1 << 1, // 保持在状态栏、刘海屏、home 指示条内侧
Default = -1, // 使用控件类型对应的平台默认值
All = 1 << 15 // 遵守所有安全区域内边距(限制最严格)
}SoftInputContainerSafeAreaRegions.Container | SafeAreaRegions.SoftInputSafeAreaEdges Struct
SafeAreaEdges 结构体
csharp
public readonly struct SafeAreaEdges
{
public SafeAreaRegions Left { get; }
public SafeAreaRegions Top { get; }
public SafeAreaRegions Right { get; }
public SafeAreaRegions Bottom { get; }
// Uniform — same value for all four edges
public SafeAreaEdges(SafeAreaRegions uniformValue)
// Horizontal / Vertical
public SafeAreaEdges(SafeAreaRegions horizontal, SafeAreaRegions vertical)
// Per-edge
public SafeAreaEdges(SafeAreaRegions left, SafeAreaRegions top,
SafeAreaRegions right, SafeAreaRegions bottom)
}Static presets: , , .
SafeAreaEdges.NoneSafeAreaEdges.AllSafeAreaEdges.Defaultcsharp
public readonly struct SafeAreaEdges
{
public SafeAreaRegions Left { get; }
public SafeAreaRegions Top { get; }
public SafeAreaRegions Right { get; }
public SafeAreaRegions Bottom { get; }
// 统一值 —— 四个边使用相同配置
public SafeAreaEdges(SafeAreaRegions uniformValue)
// 水平/垂直分开配置
public SafeAreaEdges(SafeAreaRegions horizontal, SafeAreaRegions vertical)
// 逐边配置
public SafeAreaEdges(SafeAreaRegions left, SafeAreaRegions top,
SafeAreaRegions right, SafeAreaRegions bottom)
}静态预设值:、、。
SafeAreaEdges.NoneSafeAreaEdges.AllSafeAreaEdges.DefaultXAML Type Converter
XAML 类型转换器
Follows Thickness-like comma-separated syntax:
xaml
<!-- Uniform -->
SafeAreaEdges="Container"
<!-- Horizontal, Vertical -->
SafeAreaEdges="Container, SoftInput"
<!-- Left, Top, Right, Bottom -->
SafeAreaEdges="Container, Container, Container, SoftInput"遵循类似 Thickness 的逗号分隔语法:
xaml
<!-- 统一值 -->
SafeAreaEdges="Container"
<!-- 水平值, 垂直值 -->
SafeAreaEdges="Container, SoftInput"
<!-- 左, 上, 右, 下 -->
SafeAreaEdges="Container, Container, Container, SoftInput"Control Defaults
控件默认值
| Control | Default | Notes |
|---|---|---|
| | Edge-to-edge. Breaking change from .NET 9 on Android. |
| | Respects bars/notch, flows under keyboard |
| | iOS maps to automatic content insets. Only |
| | Inherits parent behavior |
| | Inherits parent behavior |
| 控件 | 默认值 | 备注 |
|---|---|---|
| | 边到边。这是 .NET 9 之后 Android 端的重大变更。 |
| | 适配系统栏/刘海屏,内容可延伸到键盘下方 |
| | iOS 端映射为自动内容内边距,仅 |
| | 继承父容器行为 |
| | 继承父容器行为 |
Breaking Changes from .NET 9
.NET 9 以来的重大变更
ContentPage default changed to None
NoneContentPage 默认值改为 None
NoneIn .NET 9, Android behaved like . In .NET 10, the default is on all platforms. If your Android content goes behind the status bar after upgrading:
ContentPageContainerNonexaml
<!-- .NET 10 default — content extends under status bar -->
<ContentPage>
<!-- Restore .NET 9 Android behavior -->
<ContentPage SafeAreaEdges="Container">在 .NET 9 中,Android 端 的行为等同于 。在 .NET 10 中,所有平台的默认值均为 。如果升级后 Android 内容显示在状态栏后方:
ContentPageContainerNonexaml
<!-- .NET 10 默认行为 —— 内容延伸到状态栏下方 -->
<ContentPage>
<!-- 恢复 .NET 9 Android 端的行为 -->
<ContentPage SafeAreaEdges="Container">WindowSoftInputModeAdjust.Resize removed
WindowSoftInputModeAdjust.Resize 已移除
If you used in .NET 9, replace it with on the ContentPage for equivalent keyboard avoidance.
WindowSoftInputModeAdjust.ResizeSafeAreaEdges="All"如果你在 .NET 9 中使用了 ,可在 ContentPage 上设置 实现等效的键盘避让效果。
WindowSoftInputModeAdjust.ResizeSafeAreaEdges="All"Usage Patterns
使用示例
Edge-to-edge immersive content
边到边沉浸式内容
Set on both page and layout — layouts default to :
NoneContainerxaml
<ContentPage SafeAreaEdges="None">
<Grid SafeAreaEdges="None">
<Image Source="background.jpg" Aspect="AspectFill" />
<VerticalStackLayout Padding="20" VerticalOptions="End">
<Label Text="Overlay text" TextColor="White" FontSize="24" />
</VerticalStackLayout>
</Grid>
</ContentPage>在页面和布局上同时设置 —— 布局的默认值为 :
NoneContainerxaml
<ContentPage SafeAreaEdges="None">
<Grid SafeAreaEdges="None">
<Image Source="background.jpg" Aspect="AspectFill" />
<VerticalStackLayout Padding="20" VerticalOptions="End">
<Label Text="Overlay text" TextColor="White" FontSize="24" />
</VerticalStackLayout>
</Grid>
</ContentPage>Forms and critical content
表单和核心内容
xaml
<ContentPage SafeAreaEdges="All">
<VerticalStackLayout Padding="20">
<Label Text="Safe content" FontSize="18" />
<Entry Placeholder="Enter text" />
<Button Text="Submit" />
</VerticalStackLayout>
</ContentPage>xaml
<ContentPage SafeAreaEdges="All">
<VerticalStackLayout Padding="20">
<Label Text="Safe content" FontSize="18" />
<Entry Placeholder="Enter text" />
<Button Text="Submit" />
</VerticalStackLayout>
</ContentPage>Keyboard-aware chat layout
适配键盘的聊天布局
xaml
<ContentPage>
<Grid RowDefinitions="*,Auto"
SafeAreaEdges="Container, Container, Container, SoftInput">
<ScrollView Grid.Row="0">
<VerticalStackLayout Padding="20" Spacing="10">
<Label Text="Messages" FontSize="24" />
</VerticalStackLayout>
</ScrollView>
<Border Grid.Row="1" BackgroundColor="LightGray" Padding="20">
<Grid ColumnDefinitions="*,Auto" Spacing="10">
<Entry Placeholder="Type a message..." />
<Button Grid.Column="1" Text="Send" />
</Grid>
</Border>
</Grid>
</ContentPage>xaml
<ContentPage>
<Grid RowDefinitions="*,Auto"
SafeAreaEdges="Container, Container, Container, SoftInput">
<ScrollView Grid.Row="0">
<VerticalStackLayout Padding="20" Spacing="10">
<Label Text="Messages" FontSize="24" />
</VerticalStackLayout>
</ScrollView>
<Border Grid.Row="1" BackgroundColor="LightGray" Padding="20">
<Grid ColumnDefinitions="*,Auto" Spacing="10">
<Entry Placeholder="Type a message..." />
<Button Grid.Column="1" Text="Send" />
</Grid>
</Border>
</Grid>
</ContentPage>Mixed: edge-to-edge header + safe body + keyboard footer
混合布局:边到边头部 + 适配安全区域的主体 + 键盘避让底部
xaml
<ContentPage SafeAreaEdges="None">
<Grid RowDefinitions="Auto,*,Auto">
<Grid BackgroundColor="{StaticResource Primary}">
<Label Text="App Header" TextColor="White" Margin="20,40,20,20" />
</Grid>
<ScrollView Grid.Row="1" SafeAreaEdges="Container">
<!-- Use Container, not All — ScrollView only honors Container and None -->
<VerticalStackLayout Padding="20">
<Label Text="Main content" />
</VerticalStackLayout>
</ScrollView>
<Grid Grid.Row="2" SafeAreaEdges="SoftInput"
BackgroundColor="LightGray" Padding="20">
<Entry Placeholder="Type a message..." />
</Grid>
</Grid>
</ContentPage>xaml
<ContentPage SafeAreaEdges="None">
<Grid RowDefinitions="Auto,*,Auto">
<Grid BackgroundColor="{StaticResource Primary}">
<Label Text="App Header" TextColor="White" Margin="20,40,20,20" />
</Grid>
<ScrollView Grid.Row="1" SafeAreaEdges="Container">
<!-- 使用 Container 而非 All —— ScrollView 仅支持 Container 和 None -->
<VerticalStackLayout Padding="20">
<Label Text="Main content" />
</VerticalStackLayout>
</ScrollView>
<Grid Grid.Row="2" SafeAreaEdges="SoftInput"
BackgroundColor="LightGray" Padding="20">
<Entry Placeholder="Type a message..." />
</Grid>
</Grid>
</ContentPage>Programmatic (C#)
代码实现(C#)
csharp
var page = new ContentPage
{
SafeAreaEdges = SafeAreaEdges.All
};
var grid = new Grid
{
SafeAreaEdges = new SafeAreaEdges(
left: SafeAreaRegions.Container,
top: SafeAreaRegions.Container,
right: SafeAreaRegions.Container,
bottom: SafeAreaRegions.SoftInput)
};csharp
var page = new ContentPage
{
SafeAreaEdges = SafeAreaEdges.All
};
var grid = new Grid
{
SafeAreaEdges = new SafeAreaEdges(
left: SafeAreaRegions.Container,
top: SafeAreaRegions.Container,
right: SafeAreaRegions.Container,
bottom: SafeAreaRegions.SoftInput)
};Decision Framework
选型指南
| Scenario | SafeAreaEdges value |
|---|---|
| Forms, critical inputs | |
| Photo viewer, video player, game | |
| Scrollable content with fixed header/footer | |
| Chat/messaging with bottom input bar | Per-edge: |
| Blazor Hybrid app | |
| 场景 | SafeAreaEdges 取值 |
|---|---|
| 表单、核心输入区域 | |
| 图片查看器、视频播放器、游戏 | |
| 带固定头部/底部的可滚动内容 | |
| 带底部输入框的聊天/消息界面 | 逐边设置: |
| Blazor Hybrid 应用 | 页面设置 |
Blazor Hybrid Integration
Blazor Hybrid 集成
For Blazor Hybrid apps, let CSS handle safe areas to avoid double-padding.
- Page stays edge-to-edge (default in .NET 10):
xaml
<ContentPage SafeAreaEdges="None">
<BlazorWebView HostPage="wwwroot/index.html">
<BlazorWebView.RootComponents>
<RootComponent Selector="#app" ComponentType="{x:Type local:Routes}" />
</BlazorWebView.RootComponents>
</BlazorWebView>
</ContentPage>- Add in
viewport-fit=cover:index.html
html
<meta name="viewport" content="width=device-width, initial-scale=1.0,
maximum-scale=1.0, user-scalable=no, viewport-fit=cover" />- Use CSS functions:
env()
css
body {
padding-top: env(safe-area-inset-top);
padding-bottom: env(safe-area-inset-bottom);
padding-left: env(safe-area-inset-left);
padding-right: env(safe-area-inset-right);
}Available CSS environment variables: , , , .
env(safe-area-inset-top)env(safe-area-inset-bottom)env(safe-area-inset-left)env(safe-area-inset-right)对于 Blazor Hybrid 应用,建议交给 CSS 处理安全区域以避免双重内边距。
- 页面保持边到边(.NET 10 默认行为):
xaml
<ContentPage SafeAreaEdges="None">
<BlazorWebView HostPage="wwwroot/index.html">
<BlazorWebView.RootComponents>
<RootComponent Selector="#app" ComponentType="{x:Type local:Routes}" />
</BlazorWebView.RootComponents>
</BlazorWebView>
</ContentPage>- 在 中添加
index.html:viewport-fit=cover
html
<meta name="viewport" content="width=device-width, initial-scale=1.0,
maximum-scale=1.0, user-scalable=no, viewport-fit=cover" />- 使用 CSS 函数:
env()
css
body {
padding-top: env(safe-area-inset-top);
padding-bottom: env(safe-area-inset-bottom);
padding-left: env(safe-area-inset-left);
padding-right: env(safe-area-inset-right);
}可用的 CSS 环境变量:、、、。
env(safe-area-inset-top)env(safe-area-inset-bottom)env(safe-area-inset-left)env(safe-area-inset-right)Migration from Legacy APIs
从旧版 API 迁移
| Legacy (.NET 9 and earlier) | New (.NET 10+) |
|---|---|
| |
| |
| |
The legacy properties still compile but are marked obsolete. maps internally to .
IgnoreSafeArea="True"SafeAreaRegions.Nonexaml
<!-- .NET 9 (legacy, iOS-only) -->
<ContentPage xmlns:ios="clr-namespace:Microsoft.Maui.Controls.PlatformConfiguration.iOSSpecific;assembly=Microsoft.Maui.Controls"
ios:Page.UseSafeArea="True">
<!-- .NET 10+ (cross-platform) -->
<ContentPage SafeAreaEdges="Container">| 旧版(.NET 9 及更早) | 新版(.NET 10+) |
|---|---|
| |
| |
| 在 ContentPage 上设置 |
旧版属性仍可编译,但已标记为过时。 内部会映射为 。
IgnoreSafeArea="True"SafeAreaRegions.Nonexaml
<!-- .NET 9(旧版,仅 iOS 可用) -->
<ContentPage xmlns:ios="clr-namespace:Microsoft.Maui.Controls.PlatformConfiguration.iOSSpecific;assembly=Microsoft.Maui.Controls"
ios:Page.UseSafeArea="True">
<!-- .NET 10+(跨平台) -->
<ContentPage SafeAreaEdges="Container">Platform-Specific Behavior
平台特定行为
iOS & Mac Catalyst
iOS & Mac Catalyst
- Safe area insets cover: status bar, navigation bar, tab bar, notch/Dynamic Island, home indicator
- includes the keyboard when visible
SoftInput - Insets update automatically on rotation and UI visibility changes
- with
ScrollViewmaps toDefaultUIScrollViewContentInsetAdjustmentBehavior.Automatic
Transparent navigation bar for content behind the nav bar:
xaml
<Shell Shell.BackgroundColor="#80000000" Shell.NavBarHasShadow="False" />- 安全区域内边距覆盖:状态栏、导航栏、标签栏、刘海屏/灵动岛、home 指示条
- 包含可见状态下的键盘
SoftInput - 旋转和 UI 可见性变化时内边距会自动更新
- 带 属性的
Default映射为ScrollViewUIScrollViewContentInsetAdjustmentBehavior.Automatic
实现内容延伸到导航栏后方的透明导航栏:
xaml
<Shell Shell.BackgroundColor="#80000000" Shell.NavBarHasShadow="False" />Android
Android
- Safe area insets cover: system bars (status/navigation) and display cutouts
- includes the soft keyboard
SoftInput - MAUI uses and
WindowInsetsCompatinternallyWindowInsetsAnimationCompat - Behavior varies by Android version and OEM edge-to-edge settings
- 安全区域内边距覆盖:系统栏(状态/导航)和屏幕挖孔
- 包含软键盘
SoftInput - MAUI 内部使用 和
WindowInsetsCompat实现WindowInsetsAnimationCompat - 行为会随 Android 版本和 OEM 边到边设置有所不同
Common Pitfalls
常见问题
-
Forgetting to seton the layout too.
Nonemakes the page edge-to-edge, but child layouts default toContentPage SafeAreaEdges="None"and still pad inward. SetContaineron both page and layout for truly immersive content.None -
Usingdirectly on ScrollView. ScrollView manages its own content insets and ignores
SoftInput. Wrap the ScrollView in a Grid or StackLayout and applySoftInputthere.SoftInput -
Confusingwith
Default.Nonemeans "platform default for this control type" — on ScrollView (iOS) this enables automatic content insets.Defaultmeans "no safe area padding at all."None -
Double-padding in Blazor Hybrid. Settingon the page and using CSS
SafeAreaEdges="Container"results in doubled insets. Pick one approach — CSS is recommended for Blazor.env(safe-area-inset-*) -
Missingin Blazor. Without this meta tag, CSS
viewport-fit=covervalues are always zero on iOS.env(safe-area-inset-*) -
Assuming .NET 9 behavior on Android. After upgrading to .NET 10, Androiddefaults to
ContentPage(was effectivelyNone). AddContainerto restore the previous behavior.SafeAreaEdges="Container" -
Using legacyin new code. The old API is iOS-only and obsolete. Always use
ios:Page.UseSafeAreafor cross-platform safe area management.SafeAreaEdges
-
忘记同时给布局设置。
None只会让页面变为边到边,但子布局默认值为ContentPage SafeAreaEdges="None"仍会添加内边距。要实现完全沉浸式内容,需要在页面和布局上同时设置Container。None -
直接在 ScrollView 上使用。 ScrollView 会自行管理内容内边距,会忽略
SoftInput设置。请将 ScrollView 包裹在 Grid 或 StackLayout 中,在父容器上应用SoftInput。SoftInput -
混淆和
Default。None意为“该控件类型的平台默认值”——在 iOS 端的 ScrollView 上会启用自动内容内边距。Default意为“完全不添加安全区域内边距”。None -
Blazor Hybrid 中的双重内边距。 同时在页面上设置和使用 CSS
SafeAreaEdges="Container"会导致内边距翻倍。请选择一种方案——Blazor 推荐使用 CSS。env(safe-area-inset-*) -
Blazor 中缺少。 没有这个 meta 标签的话,iOS 端 CSS
viewport-fit=cover的值会始终为 0。env(safe-area-inset-*) -
假设 Android 端保持 .NET 9 的行为。 升级到 .NET 10 后,Android 端默认值为
ContentPage(之前实际为None)。如需恢复旧行为请添加Container。SafeAreaEdges="Container" -
在新代码中使用旧版。 旧 API 仅支持 iOS 且已过时。跨平台安全区域管理请始终使用
ios:Page.UseSafeArea。SafeAreaEdges
Checklist
检查清单
- Android upgrade: added if content goes under status bar
SafeAreaEdges="Container" - Edge-to-edge: set on both page and layout
None - ScrollView keyboard avoidance uses wrapper Grid, not ScrollView's own
SafeAreaEdges - Blazor Hybrid: using either XAML or CSS safe areas, not both
- in Blazor's
viewport-fit=coverindex.htmltag<meta viewport> - Legacy /
UseSafeAreamigrated toIgnoreSafeAreaSafeAreaEdges
- Android 升级:如果内容显示在状态栏下方,已添加
SafeAreaEdges="Container" - 边到边布局:页面和布局上都设置了
None - ScrollView 键盘避让使用了外层 Grid 包裹,而非直接设置 ScrollView 的
SafeAreaEdges - Blazor Hybrid:仅使用 XAML 或 CSS 其中一种方式处理安全区域,没有同时使用
- Blazor 的
index.html标签中已添加<meta viewport>viewport-fit=cover - 旧版 /
UseSafeArea已迁移到IgnoreSafeAreaSafeAreaEdges