跳过主要内容
教程

使用 Angular 和 Capacitor 构建移动应用

了解如何使用 Angular、Capacitor 和优化 Capgo 原生导航、过渡和 iOS 布局最佳实践来创建移动应用

马丁·多纳迪厄

马丁·多纳迪厄

内容营销人员

使用 Angular 和 Capacitor 构建移动应用

本教程中,我们将从一个新的 Angular 应用程序开始,逐步过渡到使用 Capacitor 的原生移动应用程序。您还可以添加 Capgo 原生导航和过渡,使用 tailwind-capacitor 来安全区域。

Capacitor 允许您轻松将 Angular 网络应用程序转换为原生移动应用程序,无需进行重大修改或学习新的技能,如 React Native。

通过几个简单的步骤,大多数 Angular 应用程序都可以转换为移动应用程序。

本教程将指导您完成整个过程,首先从一个新的 Angular 应用程序开始,然后使用 Capacitor 进入原生移动应用程序的领域。您还可以使用 Capgo 原生导航、过渡和 tailwind-capacitor 来安全区域。

关于 Capacitor

CapacitorJS 是一个革命性的工具!您可以轻松将其集成到任何 web 项目中,它将您的应用程序包装在一个原生的 webview 中,生成原生的 Xcode 和 Android Studio 项目。它的插件还提供了对原生设备功能的访问,例如通过 JS 桥的摄像头。

使用 Capacitor,您可以获得一个出色的原生移动应用程序,无需复杂的设置或陡峭的学习曲线。它的 API 和功能流线化使其成为轻松集成到您的项目中的一个理想选择。相信我,您将惊叹于如何轻松地使用 Capacitor 实现一个功能齐全的原生应用程序!

准备您的 Angular 应用程序

要创建一个新的 Angular 应用程序,请运行以下命令:

ng new my-app
cd my-app

选择“Angular”时,请选择Angular版本。

为了创建一个原生移动应用,我们需要一个 export 项目的 因此,让我们在我们的 package.json

{
  "scripts": {
    // ...
    "build": "ng build --prod"
  }
}

中添加一个简单的脚本,这可以用来构建和复制Angular项目: build执行命令后 dist ,您应该能够在项目根目录看到一个新的

This folder will be used by Capacitor later on, but for now, we must set it up correctly.

这个文件夹将由Capacitor稍后使用,但现在我们必须正确设置它。

将__CAPGO_KEEP_0__添加到您的Angular应用中 sync 命令。

首先,我们可以将 Capacitor CLI 作为开发依赖项安装,并在项目中设置它。在设置过程中,您可以按“回车”键以接受名称和包ID的默认值。

接下来,我们需要安装核心包和iOS和Android平台的相关包。

Finally, we can add the platforms, and Capacitor will create folders for each platform at the root of our project:

# 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

__CAPGO_KEEP_0__ 将为每个平台在项目根目录创建文件夹: 到目前为止,您应该能够在Angular项目中观察到新的 ios

android

为了以后访问 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 将同步所有的web code 到native平台的正确位置,以便它们可以在应用中显示。

此外,同步命令可能会更新native平台并安装插件,因此当您安装新的 Capacitor 插件 时,需要重新运行 npx cap sync 命令。

您可能没有注意到,但您已经完成了,所以让我们在设备上看看应用!

构建和部署原生应用

为了开发iOS应用,您需要 Xcode 需要安装 Xcode,针对 Android 应用程序,您需要安装 Android Studio 如果您打算将应用程序发布到应用商店,则需要在 iOS 和 Android 上注册 Apple Developer Program 和 Google Play Console。

如果您是新手,想开始原生移动开发,可以使用 Capacitor CLI 来轻松打开原生项目:

npx cap open ios
npx cap open android

一旦您设置了原生项目,部署应用程序到连接的设备就很容易了。在 Android Studio 中,只需等待所有内容就绪,然后您可以在不更改任何设置的情况下将应用程序部署到连接的设备。以下是示例:

android-studio-run

在 Xcode 中,您需要设置签名账户才能将应用程序部署到真实设备,而不是仅仅在模拟器上运行。如果您之前没有这样做过,Xcode 会指导您完成此过程(但请再次注意,您必须注册为开发者)。随后,您可以简单地点击播放来在连接的设备上运行应用程序,您可以在顶部选择设备。以下是示例:

xcode-run

恭喜!您已经成功将 Angular 网络应用程序部署到移动设备。以下是示例:

angular-mobile-app

但请稍等,开发期间还有更快的方法……

Capacitor Live Reload

现在你可能已经习惯了所有现代框架都有热重载的功能,好消息是你可以在移动设备上实现相同的功能 只需花费最少的努力! 通过让__CAPGO_KEEP_0__应用从特定的URL加载内容,来启用对本地托管应用的访问,

并且在你的网络上启用实时重载功能 第一步是确定你的本地IP地址。如果你使用的是Mac,通过在终端中运行以下命令可以找到它: by having the Capacitor app load the content from the specific URL.

然后查找IPv4地址

ipconfig getifaddr en0

我们可以通过在文件中添加另一个条目来指示__CAPGO_KEEP_0__从服务器直接加载应用:

ipconfig

文件:

Capacitor Live Reload capacitor.config.ts __CAPGO_KEEP_0__ Live Reload

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 应用中更改了什么 ,应用将自动重新加载

并显示更改! __CAPGO_KEEP_0__ __CAPGO_KEEP_1__

请注意 如果您安装了新插件,如摄像头插件,它仍然需要重新构建您的原生项目。这是因为原生文件已更改,无法在飞行中完成。

请注意,您应该在配置中使用正确的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

点击按钮后,您可以亲眼目睹美丽的原生分享对话框的运行!

接下来,您可以让应用程序在iOS和Android上感觉更原生,使用Capgo导航和过渡,并解决常见的iOS布局问题,例如水平溢出或裁剪安全区域。

使用Capgo原生导航和过渡来实现原生感知UI

我已经工作了几年, Ionic 来构建跨平台应用程序,但将其与Angular集成时,需要进行hacky操作,并且很少值得在已经有 Tailwind CSS.

For a native mobile feel in an Angular + Capacitor app, use Capgo plugins instead of web-only UI kits like Konsta UI:

安装双方:

bun add @capgo/capacitor-native-navigation @capgo/capacitor-transitions
bunx cap sync

使用 CSS inset 模式配置原生导航,以便网页内容尊严地尊严原生导航条:

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

await NativeNavigation.configure({
  contentInsetMode: 'css',
  animationDuration: 360,
  glass: {
    effect: 'liquidGlass',
  },
});

呈现 Liquid Glass tab 条 (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/capacitor-native-navigation使用 @capgo/capacitor-transitions.

安全区域与Tailwind

在Tailwind CSS中使用设备安全区域,请使用 @capgo/tailwind-capacitor (发布为 tailwind-capacitor 在npm上发布。它提供 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设置缺少什么,请 在GitHub上打开一个PR.

解决 iOS 布局问题 (视口、安全区域和水平溢出)

如果 iOS 内容看起来被裁剪、偏移或水平滚动,仅添加或调整视口标签通常无法解决问题。按照以下顺序检查这些问题。 overflow-x: hidden 确保视口元标签正确应用

,在 src/index.html仅从根级容器中处理 iOS 安全区域 <head>:

<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover" />

创建一个单独的应用 shell,并在其中应用安全区域填充 — 不要在多个嵌套组件中这样做:

将所有页面内容包装在

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);
}

在头部、模态窗口和布局容器中重复应用安全区域填充通常会使 UI 看起来被裁剪或过大。 .app-shell使用

@__CAPGO_KEEP_0__/tailwind-__CAPGO_KEEP_1__ @capgo/tailwind-capacitor您可以使用类似于的工具来实现相同的填充 pt-safe pb-safe px-safe 在单个 shell 中

设置 Capacitor iOS contentInsetnever 首先

在,prefer native inset disabled 和让 CSS(或 Native Navigation 的)拥有安全区域: capacitor.config.ts混合 __CAPGO_KEEP_0__ 的自动内容内边距与 CSS contentInsetMode: 'css'填充是双倍间距的常见原因。

const config: CapacitorConfig = {
  appId: 'com.example.myapp',
  appName: 'my-app',
  webDir: 'www',
  ios: {
    contentInset: 'never',
  },
};

Mixing Capacitor’s automatic content inset with CSS env(safe-area-inset-*) 通常的凶手是使用

元素

In 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 使用 w-full 在可能的情况下,许多水平溢出问题来自 100vw / w-screen, 重复的安全区域填充, 或者固定宽度容器 —— 不是来自视口元标签本身。

结论

Capacitor 是基于现有 Web 项目构建原生应用的优秀选择,提供了一个简单的方式来共享 code 并保持一致的 UI。

并且,通过添加 Capgo, 添加实时更新到您的应用程序变得更加容易,确保您的用户始终可以访问最新的功能和 bug 修复。

如果您想学习如何将Capgo添加到您的Angular应用中,请查看下一篇文章:

从Building Mobile Apps with Angular和Capacitor继续

如果您正在使用 Building Mobile Apps with Angular和Capacitor 来规划原生媒体和界面行为,连接它与 使用@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

Capacitor 应用实时更新

当一个 web层 bug 活跃时,通过 Capgo 将修复直接部署,而不是等待几天的应用商店审批。用户在后台接收更新,而原生变化仍然在正常的审批路径中。

立即开始

最新博客

Capgo 为您提供创建真正专业的移动应用所需的最佳见解。