> 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` 借助这个 Hook，可以读取当前界面的参数并动态使用。

#### `useParams` Hook 使用示例

下面的示例会获取通过 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.
