在本教程中,我们将从一个新的 Angular 在本教程中,我们将从一个新的 Angular 应用开始,然后使用 Capacitor 进入原生移动应用领域。您还可以添加 Capgo 原生导航和过渡以获得原生移动体验,并使用 tailwind-capacitor 来安全区域。
Capacitor 允许您轻松将 Angular 网页应用转换为原生移动应用,无需进行重大修改或学习新的技能,如 React Native。
仅需几步,绝大多数Angular应用程序就可以转化为移动应用。
本教程将指导您完成整个过程,首先使用新Angular应用程序,然后将Capacitor引入到原生移动应用程序中。您还可以使用Capgo Native Navigation, Transitions, 和tailwind-capacitor来实现安全区域。
关于Capacitor
CapacitorJS是一个革命性的工具!您可以轻松将其引入任何Web项目,并将其包装在原生Webview中,生成原生Xcode和Android Studio项目。其插件还提供访问原生设备功能的JS桥,如摄像头。
使用Capacitor,您可以获得一个无需复杂设置或陡峭学习曲线的精美原生移动应用。其轻薄API和流畅的功能使其成为轻松集成到您的项目中的理想选择。相信我,您将惊叹于如何轻松地使用Capacitor实现一个功能齐全的原生应用。
准备您的Angular应用程序
要创建一个新的Angular应用程序,请运行以下命令:
ng new my-app
cd my-app
选择“Angular”时会提示您选择Angular版本。
为了创建一个原生移动应用,我们需要导出我们的项目。因此,让我们在我们的 package.json 中添加一个简单的脚本。 项目导出 可以用来构建和复制Angular项目的工具:
{
"scripts": {
// ...
"build": "ng build --prod"
}
}
执行命令后 build你应该在项目根目录下看到一个新的 dist 文件夹。这个文件夹将由Capacitor稍后使用,但现在我们必须正确设置它。
This folder will be used by Capacitor later on, but for now, we must set it up correctly.
Adding Capacitor to Your Angular App
命令。 sync 首先,我们可以将Capacitor和Capacitor CLI安装为开发依赖项,然后在项目中设置它。在设置过程中,你可以按“回车”键以接受默认的名称和包ID。
接下来,我们需要安装核心包和iOS和Android平台的相关包。 Capacitor CLI __CAPGO_KEEP_1__
__CAPGO_KEEP_0__
最后,我们可以添加平台,Capacitor将为每个平台在项目根目录创建文件夹:
# Install the Capacitor CLI locally
npm install -D @capacitor/cli
# Initialize Capacitor in your Angular project
npx cap init
# Install the required packages
npm install @capacitor/core @capacitor/ios @capacitor/android
# Add the native platforms
npx cap add ios
npx cap add android
到目前为止,您应该能够观察到新的 ios 和 android 文件夹在您的Angular项目中。
这些是真正的本机项目!
要访问Android项目,必须安装 Android Studio。对于iOS,需要Mac,并且应该安装 Xcode.
此外,您应该找到一个 capacitor.config.ts 项目中的文件,包含一些基本的Capacitor设置,用于同步过程。您需要注意的是 webDir指向构建命令的结果。当前值不准确。
要修复这个问题,请打开 capacitor.config.json 文件并更新 webDir:
{
"appId": "com.example.app",
"appName": "my-app",
"webDir": "dist"
}
您可以通过执行以下命令来尝试它:
npm run build
npx cap sync
第一个命令 npm run build 仅会构建您的Angular项目并复制静态构建,而第二个命令 npx cap sync 将所有webcode同步到原生平台的正确位置,以便在应用中显示。
另外,同步命令可能会更新本机平台并安装插件,因此当您安装新时 Capacitor 重新运行 npx cap sync 它
没有注意到,您现在实际上已经完成了,所以让我们在设备上看到应用!
构建和部署本机应用
为了开发iOS应用,您需要安装 Xcode 并且对于Android应用,您需要安装 Android Studio 此外,如果您计划将应用发布到应用商店,则需要在iOS中加入Apple Developer Program,并在Android中加入Google Play Console。
如果您是本机移动开发的新手,可以使用CapacitorCLI轻松打开两个本机项目:
npx cap open ios
npx cap open android
一旦你设置好了原生项目,部署应用到连接设备就变得简单了。在 Android Studio 中,只需等待所有内容准备就绪,然后你就可以在不更改任何设置的情况下将应用部署到连接设备。以下是一个例子:

在 Xcode 中,你需要设置签名账户才能将应用部署到真实设备,而不是仅仅是模拟器。如果你之前没有这样做过,Xcode 会指导你完成这个过程(但请记住,你必须注册为开发者)。随后,你只需点击播放即可在连接设备上运行应用,你可以在顶部选择设备。以下是一个例子:

恭喜!你成功地将 Angular 网页应用部署到了移动设备。以下是一个例子:
但等一下,还有更快的方法来做到这一点……
Capacitor Live Reload
到目前为止,你可能已经习惯了所有现代框架都有热重载的功能,好消息是你可以在移动设备上实现相同的功能 在移动设备上 只需花费最少的努力!
启用对本地托管应用的访问,使用实时重载 On your network 通过让Capacitor应用从特定的URL加载内容。
首先,我们需要找到本地IP地址。如果您使用Mac,可以通过在终端中运行以下命令来找到它:
ipconfig getifaddr en0
在Windows上运行:
ipconfig
然后查找IPv4地址。
我们可以通过在文件中添加另一个条目来指示Capacitor从服务器直接加载应用: capacitor.config.ts 请务必使用
import { CapacitorConfig } from '@capacitor/cli';
const config: CapacitorConfig = {
appId: 'com.example.app',
appName: 'my-app',
webDir: 'dist',
bundledWebRuntime: false,
server: {
url: 'http://192.168.x.xx:4200',
cleartext: true
}
};
export default config;
正确的IP和端口 ,我在这里使用了默认的Angular端口。现在,我们可以通过将这些更改复制到本地项目中来应用这些更改:
本地
npx cap copy
应用 copy 命令与 sync但它只会 将对 web 文件夹的修改和配置复制过去 而不更新原生项目。
您可以再次通过 Android Studio 或 Xcode 部署您的应用程序。之后,如果您在 Angular 应用程序中更改了什么内容 应用程序将自动重新加载 并显示更改!
请记住 如果您安装了新插件,如摄像头插件,它仍然需要重新构建原生项目。这是因为原生文件已更改,无法在实时进行。
请注意,您应该在配置中使用正确的 IP 和端口。上面的 code 块显示了示例用途的默认 Angular 端口。
使用 Capacitor 插件
让我们看看如何使用一个 Capacitor 插件的示例。我们之前提到过几次。要实现这一点,我们可以通过运行以下命令安装一个相对简单的插件:
npm i @capacitor/share
没有什么特别的关于这个 分享插件,但它仍然会弹出原生分享对话框!为了实现这一点,我们现在只需要导入包并从我们的应用中调用相应的 share() 函数,所以让我们修改 src/app/app.component.ts 到这个:
import { Component } from '@angular/core';
import { Share } from '@capacitor/share';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.scss']
})
export class AppComponent {
title = 'my-app';
async share() {
await Share.share({
title: 'Open Youtube',
text: 'Check new video on youtube',
url: 'https://www.youtube.com',
dialogTitle: 'Share with friends'
});
}
}
如前所述,当安装新插件时,我们需要执行同步操作,然后重新部署应用到我们的设备上。要实现这一点,请运行以下命令:
npx cap sync
点击按钮后,您可以亲眼目睹原生分享对话框的美丽效果!
Next, you can make the app feel more native on iOS and Android with Capgo navigation and transitions, and fix common iOS layout issues that cause horizontal overflow or cropped safe areas.
Capgo
导航和过渡,并修复常见的iOS布局问题,导致水平溢出或裁剪安全区域。 原生感知UI使用 为了构建跨平台应用,但将其与Angular集成起来很hacky,并且当你已经有 Tailwind CSS.
在Angular + Capacitor应用中,为了获得原生移动的感觉,使用Capgo插件而不是像Konsta UI这样的仅限Web的UI套件:
- @capgo/capacitor-native-navigation ——原生导航栏,Liquid Glass iOS的标签栏,Android的模糊标签栏样式。您的Angular路由器保留路由状态;插件拥有原生浏览器。
- @capgo/capacitor-transitions ——在WebView层中实现Ionic样式的页面过渡和iOS的边缘滑动返回,且不采用Ionic UI。
安装它们:
bun add @capgo/capacitor-native-navigation @capgo/capacitor-transitions
bunx cap sync
配置原生导航以使用CSS inset模式,使Web内容尊严原生导航栏:
import { NativeNavigation } from '@capgo/capacitor-native-navigation';
await NativeNavigation.configure({
contentInsetMode: 'css',
animationDuration: 360,
glass: {
effect: 'liquidGlass',
},
});
渲染一个Liquid Glass标签栏(iOS使用系统渲染;Android使用模糊的WebView背景):
import { inject } from '@angular/core';
import { Router } from '@angular/router';
const router = inject(Router);
await NativeNavigation.setTabbar({
selectedId: 'home',
labelVisibilityMode: 'labeled',
icons: true,
colors: { dynamic: true },
tabs: [
{ id: 'home', title: 'Home', icon: { svg: '...' } },
{ id: 'settings', title: 'Settings', icon: { svg: '...' } },
],
});
await NativeNavigation.addListener('tabSelect', ({ id }) => {
router.navigate([`/${id}`]);
});
Add native page transitions in your app shell:
```typescript
// app.component.ts
import { Component, CUSTOM_ELEMENTS_SCHEMA, ElementRef, ViewChild, AfterViewInit } from '@angular/core';
import { Router } from '@angular/router';
import '@capgo/capacitor-transitions';
import { initTransitions, setDirection, setupRouterOutlet } from '@capgo/capacitor-transitions';
initTransitions({ platform: 'auto' });
@Component({
selector: 'app-root',
schemas: [CUSTOM_ELEMENTS_SCHEMA],
template: `
<cap-router-outlet #outlet platform="auto" swipe-gesture="auto">
<router-outlet></router-outlet>
</cap-router-outlet>
`,
})
export class AppComponent implements AfterViewInit {
@ViewChild('outlet') outlet?: ElementRef<HTMLElement>;
constructor(private router: Router) {}
ngAfterViewInit() {
if (this.outlet?.nativeElement) {
setupRouterOutlet(this.outlet.nativeElement, { platform: 'auto', swipeGesture: 'auto' });
}
}
openSettings() {
setDirection('forward');
this.router.navigate(['/settings']);
}
}
将路由页面包裹在 cap-router-outlet, cap-page中 cap-content或呼叫 setDirection('forward') 或 setDirection('back') 查看完整指南:
使用@__CAPGO_KEEP_0__/__CAPGO_KEEP_1__-原生导航 Using @capgo/capacitor-native-navigation 使用@__CAPGO_KEEP_0__/__CAPGO_KEEP_1__-过渡 Using @capgo/capacitor-transitions.
在Tailwind CSS中,使用
@__CAPGO_KEEP_0__/tailwind-__CAPGO_KEEP_1__ @capgo/tailwind-capacitor 在__CAPGO_KEEP_0__上。它提供 tailwind-capacitor on npm). It provides safe-areas 工具和其他 Capacitor 友好的 Tailwind 插件:
bun add -D tailwind-capacitor
在 src/styles.css:
@import 'tailwindcss';
@plugin "@capgo/tailwind-capacitor/platform";
@plugin "@capgo/tailwind-capacitor/safe-areas";
使用工具,如 pt-safe, pb-safe, 和 px-safe 而不是手动添加 env(safe-area-inset-*) 。该项目正在积极开发中 — 如果您的 Angular 设置中缺少某些内容,请 open a PR on GitHub.
如果内容在 iOS 上被裁剪、偏移或水平滚动,请添加更多
或仅仅调整视口标签通常无法解决问题。按照以下顺序检查这些问题。 overflow-x: hidden 确保视口元标签已正确应用
在
open a PR on __CAPGO_KEEP_0__ src/index.html,设置视口元标签 <head>:
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover" />
从一个根包装器中处理iOS安全区域
创建一个单一的应用程序外壳并在其中应用安全区域填充 — 不在多个嵌套组件中:
html,
body,
app-root {
width: 100%;
min-height: 100%;
margin: 0;
padding: 0;
overflow-x: hidden;
}
* {
box-sizing: border-box;
}
.app-shell {
min-height: 100dvh;
width: 100%;
padding-top: env(safe-area-inset-top);
padding-right: env(safe-area-inset-right);
padding-bottom: env(safe-area-inset-bottom);
padding-left: env(safe-area-inset-left);
}
将所有页面内容包装在 .app-shell中。 复制的安全区域填充在头部、模态对话框和布局包装器中经常使 UI 看起来被裁剪或过大。
使用 @capgo/tailwind-capacitor,您可以用类似于 pt-safe pb-safe px-safe 的工具表达相同的填充。
设置Capacitor iOS contentInset 为 never 首
在 capacitor.config.ts, 优先使用原生 inset 并让 CSS (或 Native Navigation 的) contentInsetMode: 'css') 来控制安全区域:
const config: CapacitorConfig = {
appId: 'com.example.myapp',
appName: 'my-app',
webDir: 'www',
ios: {
contentInset: 'never',
},
};
混合 Capacitor 自动内容 inset 与 CSS env(safe-area-inset-*) padding 是双倍间距的常见原因。
找到真正溢出的元素
通常的罪魁祸首是使用 100vw, Tailwind w-screen, 固定像素宽度或较大的 min-width.
在 Safari Web Inspector 中,运行:
[...document.querySelectorAll('*')]
.filter(el => el.scrollWidth > document.documentElement.clientWidth)
.map(el => ({
el,
tag: el.tagName,
class: el.className,
scrollWidth: el.scrollWidth,
clientWidth: document.documentElement.clientWidth,
}));
使用 Tailwind,替换 w-screen with w-full 当可能时。许多水平溢出问题来自 100vw / w-screen,重复的安全区域填充或固定宽度容器 —— 不是来自视口元标签本身。
结论
Capacitor 是基于现有 Web 项目构建原生应用的优秀选择,提供了简单的方式来共享 code 并保持一致的 UI。
并且随着 __CAPGO_KEEP_0__ 的加入 Capgocontext
If you would like to learn how to add Capgo to your Angular app, take a look at the next article:
Keep going from Building Mobile Apps with Angular and Capacitor
如果您想学习如何将 __CAPGO_KEEP_0__ 添加到您的 Angular 应用中,请查看下一篇文章: 继续阅读 Building Mobile Apps with Angular 和 Capacitor 如果您正在使用 Building Mobile Apps with Angular 和 __CAPGO_KEEP_0__ 来规划原生媒体和界面行为,连接它与 使用@capgo/capacitor-live-activities 为@capgo/capacitor-live-activities原生能力 @capgo/capacitor-live-activities 为@capgo/capacitor-live-activities的实现细节 使用@capgo/capacitor-video-player 为@capgo/capacitor-video-player原生能力 @capgo/capacitor-video-player 为@capgo/capacitor-video-player的实现细节 使用@capgo/capacitor-native-navigation 为@capgo/capacitor-native-navigation原生能力