一次开发多端部署的组件化UI开发精髓

在鸿蒙生态中,服务卡片(Service Widget)是一种强大的界面展示形式,能够将应用的重要信息或操作前置到卡片,达到服务直达、减少体验层级的目的。而ArkTS作为鸿蒙主推的声明式开发语言,为卡片开发带来了全新的开发体验和效率提升。本文将带你全面了解鸿蒙Next ArkTS卡片开发的方方面面。

一、ArkTS卡片概述

什么是ArkTS卡片?

ArkTS卡片是基于声明式开发范式开发的服务卡片,可以将应用内的重要信息或操作前置展示。与其他类型的卡片相比,ArkTS卡片具备更强大的动效能力自定义绘制能力逻辑代码执行能力

静态卡片 vs 动态卡片

ArkTS卡片分为两种类型,它们有不同的特点和适用场景:

特性 静态卡片 动态卡片
支持能力 仅支持UI组件和布局能力 支持UI组件、布局、通用事件和自定义动效能力
适用场景 展示静态信息(UI相对固定) 有复杂业务逻辑和交互的场景
优缺点 功能简单但有效控制内存开销 功能丰富但内存开销较大
交互能力 仅可通过FormLink组件跳转到指定UIAbility 支持router、message和call三种类型的事件

二、开发环境搭建与项目创建

创建ArkTS卡片项目

在DevEco Studio中创建ArkTS卡片有两种方式:

  1. 创建工程时选择Application或Atomic Service(元服务)

  2. 已有工程中通过右键新建卡片

具体操作路径:右键点击项目 → New → Service Widget → 选择ArkTS作为开发语言 → 选择卡片模板和规格。

工程结构分析

创建完成后,工程中会新增以下卡片相关文件:

  • EntryFormAbility.ets:卡片生命周期管理文件,负责处理卡片的创建、销毁和刷新

  • WidgetCard.ets:卡片页面文件,包含UI布局和交互逻辑

  • form_config.json:卡片配置文件,定义卡片的基本信息和特性

三、ArkTS卡片开发基础

卡片生命周期

ArkTS卡片通过FormExtensionAbility类管理生命周期,需要实现以下关键回调方法:

typescript

import FormExtensionAbility from '@ohos.app.form.FormExtensionAbility';
import formBindingData from '@ohos.app.form.formBindingData';

export default class EntryFormAbility extends FormExtensionAbility {
  // 创建卡片时调用
  onAddForm(want) {
    console.info('[EntryFormAbility] onAddForm');
    let obj = {
      "title": "titleOnCreate",
      "detail": "detailOnCreate"
    };
    let formData = formBindingData.createFormBindingData(obj);
    return formData;
  }
  
  // 更新卡片时调用
  onUpdateForm(formId) {
    console.info('[EntryFormAbility] onUpdateForm');
    let obj = {
      "title": "titleOnUpdate",
      "detail": "detailOnUpdate"
    };
    let formData = formBindingData.createFormBindingData(obj);
    formProvider.updateForm(formId, formData).catch(error => {
      console.info('[EntryFormAbility] updateForm, error:' + JSON.stringify(error));
    });
  }
  
  // 销毁卡片时调用
  onRemoveForm(formId) {
    console.info('[EntryFormAbility] onRemoveForm');
  }
  
  // 其他生命周期方法...
}

基本UI组件使用

ArkTS卡片支持丰富的UI组件,以下是部分常用组件:

  • 基础组件:Text、Image、Button、TextInput等

  • 容器组件:Column、Row、Stack、List、ForEach等

  • 绘制组件:Circle、Line、Path、Rect等(用于自定义绘制)

  • 数据组件:Gauge、DataPanel、Rating、Progress等

四、实战:创建一个可复用的信息卡片组件

下面我们通过一个实际案例,创建一个可复用的信息卡片组件。

组件定义与参数配置

typescript

@Component
export struct InfoCard {
  // 支持标题、副标题展示
  @Prop title: string;
  @Prop subtitle: string;
  // 可自定义图标
  @Prop icon: string;
  // 可响应点击事件
  @Prop onTap: () => void;
  
  build() {
    Row() {
      // 图标部分
      Text(this.icon)
        .fontSize(20)
        .margin({ right: 10 })
      
      // 文字信息部分
      Column() {
        Text(this.title)
          .fontSize(16)
          .fontWeight(FontWeight.Bold)
          .textOverflow({ overflow: TextOverflow.Ellipsis })
        
        Text(this.subtitle)
          .fontSize(14)
          .opacity(0.6)
      }
      .alignItems(HorizontalAlign.Start)
      .layoutWeight(1)
    }
    .padding(12)
    .backgroundColor(Color.White)
    .borderRadius(8)
    .shadow({ radius: 4, color: '#1A000000', offsetX: 0, offsetY: 2 })
    .onClick(() => {
      if (this.onTap) {
        this.onTap();
      }
    })
  }
}

在主页面中使用组件

typescript

@Entry
@Component
struct Index {
  build() {
    Column() {
      InfoCard({
        icon: '📦',
        title: '今日订单',
        subtitle: '已完成:123单',
        onTap: () => {
          console.log('点击了订单卡片');
          // 这里可以添加跳转逻辑
        }
      })
      
      InfoCard({
        icon: '💰',
        title: '本月收入',
        subtitle: '¥18,250',
        onTap: () => {
          console.log('点击了收入卡片');
          // 这里可以添加跳转逻辑
        }
      })
    }
    .width('100%')
    .alignItems(HorizontalAlign.Center)
    .justifyContent(FlexAlign.Center)
    .height('100%')
    .backgroundColor('#ffffff')
  }
}

支持动态交互与动画效果

ArkTS卡片支持丰富的动画效果,以下是一个按钮旋转动画示例:

typescript

@Entry
@Component
struct AttrAnimationExample {
  @State rotateAngle: number = 0;

  build() {
    Column() {
      Button('change rotate angle')
        .onClick(() => {
          this.rotateAngle = 90;
        })
        .margin(50)
        .rotate({ angle: this.rotateAngle })
        .animation({
          curve: Curve.EaseOut,
          playMode: PlayMode.AlternateReverse
        })
    }.width('100%').margin({ top: 20 })
  }
}

需要注意的是,ArkTS卡片使用动画效果时有一些限制:

  • duration(动画播放时长):最长为1秒,设置大于1秒时仍为1秒

  • tempo(动画播放速度):禁止设置此参数,使用默认值1

  • delay(动画延迟执行的时长):禁止设置此参数,使用默认值0

  • iterations(动画播放次数):禁止设置此参数,使用默认值1

五、卡片配置详解

FormExtensionAbility配置

卡片需要在module.json5配置文件的extensionAbilities标签下,配置FormExtensionAbility信息:

json

{
  "module": {
    "extensionAbilities": [
      {
        "name": "EntryFormAbility",
        "srcEntry": "./ets/entryformability/EntryFormAbility.ets",
        "label": "$string:EntryFormAbility_label",
        "description": "$string:EntryFormAbility_desc",
        "type": "form",
        "metadata": [
          {
            "name": "ohos.extension.form",
            "resource": "$profile:form_config"
          }
        ]
      }
    ]
  }
}

卡片配置文件form_config.json

form_config.json文件定义了卡片的基本信息:

json

{
  "forms": [
    {
      "name": "widget",
      "displayName": "InfoCard",
      "description": "这是一个信息卡片",
      "src": "./ets/widget/pages/WidgetCard.ets",
      "uiSyntax": "arkts",
      "isDefault": true,
      "colorMode": "auto",
      "supportDimensions": ["2*2", "2*4", "4*4"],
      "defaultDimension": "2*2",
      "isDynamic": true,
      "updateEnabled": true,
      "scheduledUpdateTime": "10:30",
      "updateDuration": 1,
      "formConfigAbility": "ability://MainAbility",
      "formVisibleNotify": true,
      "metadata": {
        "customData": "your_custom_data"
      }
    }
  ]
}

关键配置项说明

  • name:卡片名称,字符串最大长度为127字节

  • src:卡片UI代码的完整路径(ArkTS卡片需要包含.ets后缀)

  • uiSyntax:卡片类型,arkts表示ArkTS卡片

  • isDynamic:是否为动态卡片(true为动态,false为静态)

  • supportDimensions:支持的卡片规格

  • updateEnabled:是否支持定时更新

  • updateDuration:更新间隔时间(小时)

六、高级功能与技巧

自定义绘制能力

ArkTS卡片开放了自定义绘制的能力,可以通过Canvas组件创建画布并进行自定义图形绘制:

typescript

@Entry
@Component
struct Card {
  private canvasWidth: number = 0;
  private canvasHeight: number = 0;
  private settings: RenderingContextSettings = new RenderingContextSettings(true);
  private context: CanvasRenderingContext2D = new CanvasRenderingContext2D(this.settings);

  build() {
    Column() {
      Row() {
        Canvas(this.context)
          .margin('5%')
          .width('90%')
          .height('90%')
          .onReady(() => {
            console.info('[ArkTSCard] onReady for canvas draw content');
            // 获取画布实际宽高
            this.canvasWidth = this.context.width;
            this.canvasHeight = this.context.height;
            
            // 绘制画布背景
            this.context.fillStyle = 'rgba(203, 154, 126, 1.00)';
            this.context.fillRect(0, 0, this.canvasWidth, this.canvasHeight);
            
            // 在画布中心绘制一个红色的圆
            this.context.beginPath();
            let radius = this.context.width / 3;
            let circleX = this.context.width / 2;
            let circleY = this.context.height / 2;
            this.context.moveTo(circleX - radius, circleY);
            this.context.arc(circleX, circleY, radius, 2 * Math.PI, 0, true);
            this.context.closePath();
            this.context.fillStyle = 'red';
            this.context.fill();
          })
      }
    }
  }
}

动态交互事件处理

动态卡片支持三种类型的事件:

  1. router事件:跳转到指定UIAbility

  2. call事件:拉起指定UIAbility到后台

  3. message事件:通过onFormEvent接口回调通知,更新卡片内容

typescript

// 在卡片中使用postCardAction接口实现交互
Button('点击跳转')
  .onClick(() => {
    // 使用router事件跳转到指定UIAbility
    postCardAction(this, {
      'action': 'router',
      'abilityName': 'MainAbility',
      'params': {
        'from': 'card'
      }
    });
  })

// 在EntryFormAbility中处理事件
onFormEvent(formId, message) {
  console.info('[EntryFormAbility] onFormEvent: ' + message);
  // 根据message内容处理不同事件
  let data = JSON.parse(message);
  if (data.event === 'refresh') {
    this.refreshCard(formId);
  }
}

七、优化建议与最佳实践

根据实际开发经验,以下是一些优化建议:

  1. 组件化设计:将卡片拆分为可复用的组件,提高代码复用率和可维护性

  2. 状态管理:合理使用@State、@Prop等装饰器管理组件状态,实现数据与UI的自动绑定

  3. 性能优化

    • 对于长列表,使用LazyForEach实现按需加载

    • 避免在卡片中执行复杂耗时的操作

    • 合理使用缓存机制减少数据获取频率

  4. 多设备适配:利用声明式布局自动适配不同设备的屏幕尺寸

  5. 拓展功能

    • 支持图标图片URL(Image渲染)

    • 支持背景色动态配置

    • 添加右侧操作按钮(如「查看」)

结语

ArkTS卡片开发是鸿蒙生态中重要的一环,它允许开发者创建高效、美观且功能丰富的服务卡片。通过声明式开发范式,我们可以更高效地处理UI变化,实现一次开发多端部署的效果。

ArkTS卡片的三大优势

  1. 统一开发范式:卡片和页面使用相同的声明式开发范式,降低学习成本,提高开发效率

  2. 强大动效能力:支持属性动画、显式动画和组件内转场,提升用户体验

  3. 深度集成鸿蒙特性:原生支持分布式能力和跨设备交互

希望本篇博客能帮助你快速上手鸿蒙Next ArkTS卡片开发,开启鸿蒙应用开发的新篇章!

Logo

讨论HarmonyOS开发技术,专注于API与组件、DevEco Studio、测试、元服务和应用上架分发等。

更多推荐