> For the complete documentation index, see [llms.txt](https://docs.decentraland.org/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.decentraland.org/creator/content-creator-zh/wei-yi-dong-duan-gou-jian/kai-fa/safe-area.md).

# 移动端安全区域

场景 UI 在移动端可以安全显示的位置——避开设备硬件边距和客户端自身控件。

在手机上，有两种互不相关的东西会占用 UI 可安全使用的屏幕空间：

* **设备的硬件边距** —— 刘海或摄像头开孔、状态栏、Home 指示条，以及圆角。绘制在它们下面的 UI 会有一部分被遮住，或者很难点击。
* **Decentraland 客户端自身的控件** —— 摇杆、聊天、个人资料、相机控件、操作按钮。放在它们下面的场景 UI 在视觉上会冲突，并争夺相同的点击。

你不必测量其中任何一个。客户端会在运行时报告这两个区域，而 SDK 会将你的 UI 布局在你所选择的区域内，并通过 [`screenInset`](/creator/content-creator-zh/chang-jing-sdk7/2d-ui/onscreen-ui.md#screen-inset-area) 渲染器选项：

| 你想要的效果             | 传入什么                                 |
| ------------------ | ------------------------------------ |
| 避开硬件边距             | 什么都不传—— `screenInset: 'device'` 是默认值 |
| 避开硬件边距 **和** 客户端控件 | `screenInset: 'interactable'`        |
| 整个屏幕，边距由你自行处理      | `screenInset: 'none'`                |

```ts
// 建议用于不能与移动端控件冲突的场景 UI
ReactEcsRenderer.setUiRenderer(uiComponent, { screenInset: 'interactable' })
```

{% hint style="warning" %}
**客户端支持**: `'interactable'` 需要移动端客户端 `1.12.1` 或更新版本。在较旧的客户端上，该区域会被报告为 0，UI 会回退为覆盖整个屏幕。同一版本还统一了 `'device'` Android 与 iOS 之间的该区域。

**在桌面端它并非无操作** —— 桌面客户端会为其自身 UI 预留大约屏幕左侧 25% 的区域，因此 `'interactable'` 也会改变你的桌面布局。可通过以下方式分支： [`isMobile()`](/creator/content-creator-zh/wei-yi-dong-duan-gou-jian/kai-fa/detect-platform.md) 如果你只想在手机上应用内边距。
{% endhint %}

参见 [屏幕内边距区域](/creator/content-creator-zh/chang-jing-sdk7/2d-ui/onscreen-ui.md#screen-inset-area) 完整参考：真实设备上并排显示的三个区域、各渲染器行为，以及它们与 [虚拟屏幕](/creator/content-creator-zh/chang-jing-sdk7/2d-ui/onscreen-ui.md#default-virtual-size).

## 客户端控件所在区域

`'interactable'` 给你该区域 **每个 explorer 为场景 UI 指定的** —— 这并不意味着所有客户端控件都一定在其外部。对于移动端客户端，它是设备安全区域减去左侧栏（聊天、个人资料、摇杆、表情）；右下角的操作按钮会绘制在该区域之上 **按设计如此**.

<figure><img src="https://2460066822-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoPnXBby9S6MrsW83Y9qZ%2Fuploads%2Fgit-blob-c0c75a80bed756d6b2b1483a7cca0cadef26c77e%2Fscreeninset-interactable.png?alt=media" alt="Scene UI inset to the area the mobile client reports as free of its own HUD"><figcaption><p><code>screenInset: 'interactable'</code> 在移动端客户端上 <code>1.12.1</code>。洋红色矩形是场景 UI，绿色轮廓表示可交互区域。左侧栏被排除在外；右下角的操作按钮位于该区域之上。</p></figcaption></figure>

所以即使使用 `'interactable'`，也要将这些区域视为拥挤区域：

* **右下角** —— 操作按钮和交互按钮会绘制在上层。放在这里的任何内容仍然可达，但会与点击操作争抢。
* **右上角** —— 个人资料和相机控件位于该区域外侧，因此紧贴该角落的 UI 会被视为客户端 HUD 的一部分。

该区域覆盖哪些内容由各个 explorer 自行决定，并且可能在不同版本之间变化。请在运行时读取，切勿硬编码，并在你目标的平台上进行检查。

## 场景 UI 应放置在哪里

* **屏幕中央** —— 需要操作的对话框，以及玩家需要阅读并作出回应的任何内容。
* **顶部居中** —— 无需操作的消息、状态和通知。
* **底部居中，位于交互按钮上方** —— 与上下文相关的提示。
* **不要放在右下角** —— 即使在可交互区域内，它也属于操作按钮的范围。

## 改为只包裹你的部分 UI

如果你通过使用 `screenInset: 'none'` 并且只想保护部分 UI，请将其包裹在 `ScreenInsetArea` 或 `InteractableArea` 组件中。每个组件都会读取其对应区域，并将其应用到子元素。请从以下位置导入它们： `@dcl/sdk/react-ecs`:

```tsx
import ReactEcs, { ReactEcsRenderer, UiEntity, ScreenInsetArea } from '@dcl/sdk/react-ecs'
import { Color4 } from '@dcl/sdk/math'

export function setupUi() {
  ReactEcsRenderer.setUiRenderer(() => (
    <ScreenInsetArea>
      {/* 一个大小为 100% × 100% 的子元素会正好填满安全内边距区域 */}
      <UiEntity
        uiTransform={{ width: '100%', height: '100%' }}
        uiBackground={{ color: Color4.create(0, 0, 0, 0.5) }}
      />
    </ScreenInsetArea>
  ), { screenInset: 'none' })
}
```

这两个组件都会使用客户端报告的值进行绝对定位，因此 `positionType` 和 `位置` 它们的 `uiTransform` 字段被保留——你为它们设置的任何值都会被忽略。所有其他 `uiTransform` 属性（`padding`, `flexDirection`, `alignItems`，…）以及 UI 组件（`uiBackground`, `onMouseDown`，…）都能正常工作。当区域发生变化时，例如屏幕旋转或系统栏出现/隐藏，它们会自动响应，并会补偿 [UI 缩放系数](/creator/content-creator-zh/chang-jing-sdk7/2d-ui/onscreen-ui.md#screen-virtual-scale)，因此无论你的虚拟屏幕尺寸如何，边距都能正确落位。

{% hint style="warning" %}
**📔 不要重复应用内边距：** 上面的 `screenInset: 'none'` 在上面的代码片段中很重要。当渲染器已经在应用对应内边距时，你又用组件包裹 UI，会让 UI 向内偏移双倍边距。二者择一即可。
{% endhint %}

{% hint style="info" %}
**📱 仅限移动端：** 设备内边距只有在 **移动端客户端**上才有真实值。在 **桌面客户端** 上它们是 `(0, 0, 0, 0)`，因此 `screenInset: 'device'` 和 `ScreenInsetArea` 组件在那里没有效果，你的 UI 渲染结果与不使用它们时完全相同。与设备内边距不同，可交互区域 *为* 在桌面端不为 0。
{% endhint %}

## 为什么这很重要

与客户端控件重叠的场景 UI 会：

* 被摇杆、交互按钮或相机控件部分遮挡。
* 与这些控件争夺点击——玩家会不小心触发其中一个。
* 让你的场景在移动端显得有问题，这会损害推荐和留存。

请始终使用以下方式在真实设备上进行验证： [预览二维码](/creator/content-creator-zh/wei-yi-dong-duan-gou-jian/kai-fa/preview-on-mobile.md).

## 相关

* [屏幕内边距区域](/creator/content-creator-zh/chang-jing-sdk7/2d-ui/onscreen-ui.md#screen-inset-area) —— 完整的 `screenInset` 参考文档。
* [移动端 UI 最佳实践](/creator/content-creator-zh/wei-yi-dong-duan-gou-jian/kai-fa/ui-best-practices.md)
* [从代码中检测平台](/creator/content-creator-zh/wei-yi-dong-duan-gou-jian/kai-fa/detect-platform.md) —— 使用 `isMobile()` 来切换布局。
* [屏幕内 UI](/creator/content-creator-zh/chang-jing-sdk7/2d-ui/onscreen-ui.md)
* [UX 与 UI 指南](/creator/content-creator-zh/chang-jing-sdk7/she-ji-ti-yan/ux-ui-guide.md)


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.decentraland.org/creator/content-creator-zh/wei-yi-dong-duan-gou-jian/kai-fa/safe-area.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
