跳过主要内容
教程

Building Mobile Apps with Angular and Capacitor

Learn how to create a mobile app with Angular, Capacitor, and enhance the Capgo Native Navigation, Transitions, and iOS layout best practices.

文章来源

马丁·多纳迪厄

作者

瓦莱里亚

审稿人

乔丹

编辑器

Building Mobile Apps with Angular and Capacitor

在本教程中,我们将从新建一个 Angular app and transition into the native mobile app realm using Capacitor. You can also add Capgo Native Navigation and Transitions for a native mobile feel, and use tailwind-capacitor for safe areas.

Capacitor allows you to easily convert your Angular web application into a native mobile app without requiring significant modifications or learning a new skill like React Native.

仅需几步,几乎所有的 Angular 应用都可以转换为移动应用。

This tutorial will guide you through the process, starting with a new Angular app and then incorporating Capacitor to move into the realm of native mobile apps. You can also use Capgo Native Navigation, Transitions, and tailwind-capacitor for safe areas.

About Capacitor

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

With Capacitor, you get a fantastic native mobile app without any complicated setup or steep learning curve. Its slim API and streamlined functionality make it a breeze to integrate into your project. Trust me, you’ll be amazed at how effortless it is to achieve a fully functional native app with Capacitor!

准备您的 Angular 应用

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

ng new my-app
cd my-app

当提示选择Angular版本时,请选择“Angular”。

为了创建一个原生移动应用,我们需要一个 export 项目的 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.

Capacitor

为了将任何 web 应用打包到原生移动容器中,我们必须遵循几个初始步骤,但之后只需执行一个命令。 sync 首先,我们可以将

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

将为每个平台在项目根目录创建文件夹:

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

文件夹。 android ios __CAPGO_KEEP_0__

这些是真正的本地项目!

为了以后访问 Android 项目,您必须安装 Android Studio对于 iOS,您需要一台 Mac,并应安装 Xcode.

此外,您应该找到一个 capacitor.config.ts file in your project, which contains some fundamental Capacitor settings utilized during the sync. The only thing you need to pay attention to is the __CAPGO_KEEP_0__设置,在同步过程中使用。您需要注意的是

webDir capacitor.config.json file 和更新 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平台的正确位置,以便在app中显示。

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

您可能已经完成了,而不自知,所以让我们在设备上看看app!

构建和部署native应用

为了开发iOS应用,您需要安装 Xcode 为了开发Android应用,您需要安装 Android Studio 此外,如果您打算将应用发布到应用商店,则需要为iOS注册Apple Developer Program,

如果您是native移动开发的新手,可以使用Capacitor CLI轻松打开两个native项目:

npx cap open ios
npx cap open android

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

android-studio-run

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

xcode-run

恭喜!您成功将Angular web应用部署到移动设备。以下是示例:

angular-mobile-app

但是,开发过程中有更快的方法……

Capacitor 实时重载

到目前为止,您可能习惯于使用所有现代框架的热重载功能,好消息是您可以轻松获得相同的功能 在移动设备上

启用对您的本地托管应用程序的实时重载 在您的网络上 通过让Capacitor应用程序从特定的URL加载内容

第一步是确定您的本地IP地址。如果您使用Mac,可以通过在终端中运行以下命令来查找此信息:

ipconfig getifaddr en0

在Windows上运行:

ipconfig

然后查找IPv4地址

我们可以通过在配置文件中添加另一个条目来指示Capacitor从服务器直接加载应用程序: capacitor.config.ts file:

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

The command is similar to but it will only copy over the changes made to the web folder and configuration, without updating the native project. 并显示变化!

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

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

As mentioned earlier, when installing new plugins, we need to perform a sync operation and then redeploy the app to our device. To do this, run the following command:

npx cap sync

After hitting the button, you can witness the beautiful native share dialog in action!

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.

Native-feeling UI with Capgo Native Navigation and Transitions

I’ve worked for years with Ionic to build cross-platform applications, but integrating it with Angular is hacky and rarely worth it when you already have Tailwind CSS For a native mobile feel in an Angular + __CAPGO_KEEP_0__ app, use __CAPGO_KEEP_1__ plugins instead of web-only UI kits like Konsta UI: @__CAPGO_KEEP_0__/__CAPGO_KEEP_1__-native-navigation — native navbar, Liquid Glass tab bar on iOS, and a blurred tab bar style on Android. Your Angular router keeps route state; the plugin owns the native chrome. @__CAPGO_KEEP_0__/__CAPGO_KEEP_1__-transitions.

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

  • @capgo/capacitor-native-navigation 接下来,您可以使应用在 iOS 和 Android 上感觉更原生,使用 __CAPGO_KEEP_0__ 导航和过渡,并修复常见的 iOS 布局问题,导致水平溢出或裁剪安全区域。
  • @capgo/capacitor-transitions —— Ionic 风格的页面过渡和 iOS 边缘滑动返回在 WebView层中,未采用 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',
  },
});

呈现液态玻璃标签栏(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') context

在导航之前。不要在本机导航拥有这些表面时重复 Web 头部或底部。 Using @capgo/capacitor-native-navigation 使用 @__CAPGO_KEEP_0__/__CAPGO_KEEP_1__-native-navigation 使用@capgo/capacitor-转换.

安全区域与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-*) 。该项目正在积极开发中—if您的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使用

With @capgo/tailwind-capacitor,你可以使用类似于 pt-safe pb-safe px-safe 在单个shell上

设置CapacitoriOS contentInsetnever 首先

capacitor.config.ts,优先使用原生边距禁用并让CSS(或Native Navigation的) contentInsetMode: 'css')拥有安全区域:

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

混合Capacitor的自动内容边距与CSS env(safe-area-inset-*) 边距是双倍间距的常见原因。

找到实际溢出元素

通常的罪魁祸首是使用 100vw, Tailwind w-screen, 固定像素宽度, 或者一个很大的 min-width.

In 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,这使得您可以轻松地将实时更新添加到应用程序中,确保您的用户始终可以访问最新的功能和修复程序。

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

继续使用Angular和 Capacitor 构建移动应用

如果您正在使用 使用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视频播放器 为@capgo/capacitor视频播放器的实现细节 使用@capgo/capacitor原生导航 为使用@capgo/capacitor原生导航的原生能力

Capacitor应用程序的即时更新

当一个web层面的bug是活跃的,通过Capgo将修复发送,而不是等待几天的应用商店批准。用户在后台接收更新,而本机更改保持在正常的审查路径中。

来自马丁的人性化支持

立即开始

最新的博客文章

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