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

原生导航

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

演示

WebP动画演示

原生导航栏、选项卡、SVG图标和样式选项以动画WebP形式呈现。

源资产
原生导航栏shell演示,展示原生导航栏、选项卡和WebView内容
原生shell
原生导航栏点击流,展示选项卡选择、推送过渡和原生后退
点击流
动态原生 SVG 图标示例,展示内联 SVG 图标、原生颜色、标签和选项卡选择
SVG 图标
动态原生导航选项示例,展示动态颜色、选中标签、徽章和缩放过渡
样式选项

指南

原生导航教程

在设备上测试

下载 Capgo 应用程序,然后扫描 QR 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,该插件将写入原生导航栏的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-过渡的组合

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

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 正常页面推送时进行动画,仅在共享元素或缩放路由时使用原生导航的缩放辅助器。

完整参考

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

如果您正在使用 使用@capgo/capacitor-native-navigation 来规划原生媒体和界面行为,连接它与 @capgo/capacitor-native-navigation 查看@capgo/capacitor-native-navigation的实现细节 开始 查看Getting Started的实现细节 使用@capgo/capacitor-live-activities 查看Using @capgo/capacitor-live-activities的原生功能 @capgo/capacitor-live-activities 查看@capgo/capacitor-live-activities的实现细节,并 使用@capgo/capacitor-video-player 为native能力在使用@capgo/capacitor-video-player中。