跳过主要内容
返回插件
@capgo/capacitor-native-navigation
教程
@capgo/capacitor-native-导航

Native Navigation

在全屏 Capacitor WebView 上渲染原生导航栏、标签栏和转场壳

演示

动画 WebP 演示

原生导航栏、标签页、SVG 图标和样式选项渲染为动画 WebP 演示。

源资产
原生导航栏、标签页和 WebView 内容的动画原生导航 shell 演示
原生 shell
动画原生导航栏、标签页选择、推送过渡和原生后退的原生导航栏流程
导航流程
动画原生 SVG 图标演示,显示内联 SVG 图标、原生着色、标签和标签页选择
SVG 图标
动画原生导航选项演示,显示动态颜色、选中标签、徽章和缩放过渡
样式选项

指南

原生导航教程

在设备上测试

下载 Capgo 应用程序,然后扫描二维码 code。

原生导航插件预览二维码 code

使用 @capgo/capacitor-native-navigation

@capgo/capacitor-native-navigation 渲染原生顶部导航、底部标签栏和路由转换壳,所有这些都在一个全屏 Capacitor WebView 上。您的 Web 框架仍然拥有路由和内容,而原生则拥有应用程序框架。

安装并同步

npm install @capgo/capacitor-native-navigation
npx cap sync

配置原生框架

import { NativeNavigation } from '@capgo/capacitor-native-navigation';

await NativeNavigation.configure({
  contentInsetMode: 'css',
  animationDuration: 360,
  colors: {
    tint: '#0f172a',
    inactiveTint: '#64748b',
  },
});

渲染原生导航栏

await NativeNavigation.setNavbar({
  title: 'Inbox',
  subtitle: 'Native chrome',
  transparent: true,
  backButton: { visible: false },
  rightItems: [
    {
      id: 'compose',
      title: 'Compose',
      icon: {
        svg: '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M12 20h9"/><path d="M16.5 3.5a2.12 2.12 0 0 1 3 3L7 19l-4 1 1-4Z"/></svg>',
      },
    },
  ],
});

渲染原生标签栏

await NativeNavigation.setTabbar({
  selectedId: 'inbox',
  labelVisibilityMode: 'selected',
  icons: true,
  colors: {
    dynamic: true,
    tint: '#0f172a',
    inactiveTint: '#64748b',
  },
  tabs: [
    {
      id: 'inbox',
      title: 'Inbox',
      icon: {
        svg: '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M4 4h16v16H4z"/><path d="m4 13 4 4h8l4-4"/></svg>',
      },
    },
    {
      id: 'search',
      title: 'Search',
      icon: {
        svg: '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="11" cy="11" r="7"/><path d="m20 20-3-3"/></svg>',
      },
    },
  ],
});

将原生事件连接到您的路由器

原生栏发射意图。您的路由器仍然执行路由更改:

await NativeNavigation.addListener('navbarBack', () => {
  router.back();
});

await NativeNavigation.addListener('navbarItemTap', ({ id }) => {
  if (id === 'compose') router.push('/compose');
});

await NativeNavigation.addListener('tabSelect', ({ id }) => {
  router.push(`/${id}`);
});

动画路由更改

在您的正常Web路由更新周围使用一个过渡事务:

const transition = await NativeNavigation.beginTransition({
  direction: 'forward',
});

router.push('/message/42');
await router.ready?.();

await NativeNavigation.setNavbar({
  title: 'Message',
  backButton: { visible: true, title: 'Inbox' },
});

await NativeNavigation.finishTransition({
  id: transition.id,
  direction: 'forward',
});

添加一个缩放过渡

使用缩放助手来处理从卡片、网格项或媒体预览打开的路由

import { beginZoomTransition, finishZoomTransition } from '@capgo/capacitor-native-navigation';

const card = document.querySelector('[data-message-card]');
if (card) {
  const transition = await beginZoomTransition(card, { cornerRadius: 18 });

  router.push('/message/42');
  await router.ready?.();

  await NativeNavigation.setNavbar({
    title: 'Message',
    backButton: { visible: true, title: 'Inbox' },
  });

  await finishZoomTransition(undefined, {
    id: transition.id,
    cornerRadius: 18,
  });
}

用原生边距填充内容

contentInsetModecss, native bars 的插件写入 CSS 变量:

.page {
  padding-top: var(--cap-native-navigation-top);
  padding-bottom: var(--cap-native-navigation-bottom);
}

图标选择

图标是原生描述符,而不是 React 或 Vue 节点。使用 SVG 时,不想打包原生资产:

const icon = {
  svg: '<svg viewBox="0 0 24 24"><path d="M3 10.5 12 3l9 7.5"/></svg>',
  template: true,
  ios: { sfSymbol: 'house.fill' },
  android: { resource: 'ic_menu_view' },
};

内联 SVG 支持 path, line, polyline, polygon, circle, 和 rect, 它涵盖了常见的图标集,如 Lucide 和 Feather。

结合 @capgo/capacitor-transitions

使用 Native Navigation 原生导航栏、标签栏、安全区域内边距和原生意图事件。使用 @capgo/capacitor-transitions 为 WebView 页面堆栈在原生 chrome 之下。

npm install @capgo/capacitor-native-navigation @capgo/capacitor-transitions
npx cap sync

初始化两次包:

import { NativeNavigation } from '@capgo/capacitor-native-navigation';
import '@capgo/capacitor-transitions';
import { initTransitions, setupRouterOutlet, setDirection } from '@capgo/capacitor-transitions/react';

initTransitions({ platform: 'auto' });

const outlet = document.querySelector('cap-router-outlet');
if (outlet) {
  setupRouterOutlet(outlet, { platform: 'auto', swipeGesture: 'auto' });
}

await NativeNavigation.configure({
  contentInsetMode: 'css',
});

保持转场出入口聚焦在页面上,而不是重复的 web 条:

<cap-router-outlet platform="auto" swipe-gesture="auto">
  <cap-page>
    <cap-content slot="content" fullscreen>
      <main class="page">Inbox content</main>
    </cap-content>
  </cap-page>
</cap-router-outlet>

同时从同一个路由动作驱动两个包:

async function openMessage(id: string) {
  setDirection('forward');
  await router.push(`/messages/${id}`);
  await NativeNavigation.setNavbar({
    title: 'Message',
    backButton: { visible: true, title: 'Inbox' },
  });
}

await NativeNavigation.addListener('navbarBack', () => {
  setDirection('back');
  router.back();
});

await NativeNavigation.addListener('tabSelect', ({ id }) => {
  setDirection('root');
  router.push(`/${id}`);
});

每次路由变化选择一个动画层。让 @capgo/capacitor-transitions 普通页面推送使用正常的动画,而使用Native Navigation的缩放帮助器仅用于共享元素或缩放路由。

完整参考

继续使用@capgo/capacitor-native-navigation

如果您正在使用 使用@capgo/capacitor-native-navigation 规划原生媒体和界面行为时,连接它与 @capgo/capacitor-native-navigation 为 @capgo/capacitor-native-navigation 的实现细节, 开始使用 为开始使用的实现细节, 使用 @capgo/capacitor-live-activities 为使用 @capgo/capacitor-live-activities 的原生能力, @capgo/capacitor-live-activities 为 @capgo/capacitor-live-activities 的实现细节, 和 使用 @capgo/capacitor-video-player 为使用 @capgo/capacitor-video-player 的原生能力,