跳过主要内容
返回插件
@capgo/capacitor-native-navigation
教程
由 github.com/Cap-go

原生导航

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

演示

动画 WebP 演示

原生导航、Chrome、标签选择、SVG 图标和样式选项以动画 WebP 演示的形式呈现。

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

指南

原生导航教程

使用 @capgo/capacitor-native-navigation

@capgo/capacitor-native-navigation 渲染原生顶部导航、底部选项卡栏和路由过渡 shell 在一个全屏 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,
  });
}

用原生内边距填充内容

contentInsetMode __CAPGO_KEEP_0__ css,插件为原生栏写入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, circlerect,涵盖常见的图标集,如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 animate普通页面推送,仅使用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 中的原生能力