> For the complete documentation index, see [llms.txt](https://developers-apps-in-toss.toss.im/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://developers-apps-in-toss.toss.im/documentation/api-and-sdk-zh/react-native/screen-navigation/layout.md).

# 布局

布局是用于一致管理在多个页面中重复出现的 UI 元素（页眉、导航栏、页脚等）的结构。定义公共布局后，可以减少代码重复，并提供一致的用户体验。

### 创建布局文件

布局是 `_layout.tsx` 通过创建文件来定义。根据文件所在位置，适用范围会不同。

```tsx
import { PropsWithChildren } from "react";

export default function Layout({ children }: PropsWithChildren) {
  return <>{children}</>;
}
```

### 设置布局适用范围

布局会根据文件路径自动应用。

* `pages/_layout.tsx`: 会全局应用于所有页面。
* `pages/about/_layout.tsx`: `intoss://{服务名}/about` 仅应用于其下的所有页面。

布局可以嵌套使用。当多个布局同时存在时，会按照上级目录的布局顺序依次应用。

```
pages/
├── _layout.tsx          // 全局布局
├── about/
│   ├── _layout.tsx     // about 部分布局
│   ├── index.tsx       // about 主页
│   └── team.tsx        // 团队介绍页面
└── index.tsx           // 主页
```

例如，如果是上述结构 `about/team.tsx` 页面会按以下顺序应用布局。

1. `pages/_layout.tsx` (全局布局)
2. `pages/about/_layout.tsx` (部分布局)
3. `pages/about/team.tsx` (实际页面组件)

这样组织后，可以将全局需要的 UI 元素与仅特定部分需要的 UI 元素分离管理。

### 布局示例

#### 全局布局

我们来创建一个对所有页面都通用的布局。

{% tabs %}
{% tab title="pages/\_layout.tsx" %}

```tsx
import { PropsWithChildren } from "react";
import { View } from "react-native";
import { Header } from "../components/Header";
import { Footer } from "../components/Footer";

export default function Layout({ children }: PropsWithChildren) {
  return (
    <View style={{ flex: 1 }}>
      <Header />
      {children}
      <Footer />
    </View>
  );
}
```

{% endtab %}

{% tab title="components/Header.tsx" %}

```tsx
import { View, Text, StyleSheet } from "react-native";

export function Header() {
  return (
    <View style={styles.header}>
      <Text style={styles.title}>我的应用</Text>
      <View style={styles.nav}>
        <Text style={styles.navItem}>首页</Text>
        <Text style={styles.navItem}>关于</Text>
        <Text style={styles.navItem}>设置</Text>
      </View>
    </View>
  );
}

const styles = StyleSheet.create({
  header: {
    padding: 16,
    backgroundColor: "#ffffff",
    borderBottomWidth: 1,
    borderBottomColor: "#e5e5e5",
  },
  title: {
    fontSize: 24,
    fontWeight: "bold",
    marginBottom: 8,
  },
  nav: {
    flexDirection: "row",
    gap: 16,
  },
  navItem: {
    fontSize: 16,
    color: "#666666",
  },
});
```

{% endtab %}

{% tab title="components/Footer.tsx" %}

```tsx
import { View, Text, StyleSheet } from "react-native";

export function Footer() {
  return (
    <View style={styles.footer}>
      <Text style={styles.copyright}>© 2024 我的应用。保留所有权利。</Text>
    </View>
  );
}

const styles = StyleSheet.create({
  footer: {
    padding: 16,
    backgroundColor: "#f5f5f5",
    alignItems: "center",
  },
  copyright: {
    fontSize: 14,
    color: "#666666",
  },
});
```

{% endtab %}
{% endtabs %}

#### 分区布局

可以创建仅在特定部分使用的布局。

{% tabs %}
{% tab title="pages/about/\_layout.tsx" %}

```tsx
import { PropsWithChildren } from "react";
import { View } from "react-native";
import { AboutSidebar } from "../../components/AboutSidebar";

export default function AboutLayout({ children }: PropsWithChildren) {
  return (
    <View style={{ flexDirection: "row" }}>
      <AboutSidebar />
      <View style={{ flex: 1 }}>{children}</View>
    </View>
  );
}
```

{% endtab %}

{% tab title="components/AboutSidebar.tsx" %}

```tsx
import { View, Text, StyleSheet } from "react-native";

export function AboutSidebar() {
  return (
    <View style={styles.sidebar}>
      <Text style={styles.title}>关于</Text>
      <View style={styles.menu}>
        <Text style={styles.menuItem}>公司介绍</Text>
        <Text style={styles.menuItem}>团队介绍</Text>
        <Text style={styles.menuItem}>历史沿革</Text>
        <Text style={styles.menuItem}>联系我们</Text>
      </View>
    </View>
  );
}

const styles = StyleSheet.create({
  sidebar: {
    width: 200,
    padding: 16,
    backgroundColor: "#f8f9fa",
    borderRightWidth: 1,
    borderRightColor: "#e5e5e5",
  },
  title: {
    fontSize: 20,
    fontWeight: "bold",
    marginBottom: 16,
  },
  menu: {
    gap: 12,
  },
  menuItem: {
    fontSize: 16,
    color: "#495057",
  },
});
```

{% endtab %}
{% endtabs %}

### 在布局中获取查询参数

布局中也可以使用查询参数。 `useParams` 通过这个钩子，可以读取当前屏幕的参数并动态使用。

#### `useParams` 钩子使用示例

下面的示例会获取通过 URL 查询参数传递的 `title` 值，并将其显示为屏幕顶部标题。

{% tabs %}
{% tab title="pages/\_layout.tsx" %}

```tsx
import { useParams } from "@granite-js/react-native";
import { PropsWithChildren } from "react";
import { View, Text } from "react-native";

export default function Layout({ children }: PropsWithChildren) {
  // 获取当前屏幕的参数。
  const params = useParams({ strict: false });

  // 获取 'title' 参数并设置默认值。
  const title = params?.title ?? "默认标题";

  return (
    <View style={{ flex: 1 }}>
      {/* 动态生成的头部 */}
      <View style={{ padding: 16, backgroundColor: "#f0f0f0" }}>
        <Text style={{ fontSize: 20, fontWeight: "bold" }}>{title}</Text>
      </View>
      {/* 渲染子组件 */}
      <View style={{ flex: 1 }}>{children}</View>
    </View>
  );
}
```

{% endtab %}
{% endtabs %}

### 参考文档

* [页面跳转](/documentation/api-and-sdk-zh/react-native/screen-navigation/navigation.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://developers-apps-in-toss.toss.im/documentation/api-and-sdk-zh/react-native/screen-navigation/layout.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.
