​简介

服务卡片框架提供了FormExtensionAbility基类,通过继承此基类,实现调用服务卡片的生命周期函数,来实现具体卡片的功能。

开放了属性动画和显式动画,增加了自定义绘制的能力,可以使用Canvas画布组件自定义绘制和构建更多样的显示和交互效果。允许卡片中运行逻辑代码,业务逻辑可以在卡片内部自闭环。

不支持功能


不支持导入共享包。


不支持native语言,仅支持声明式范式的部分组件、事件、动效、数据管理、状态管理和API能力。


暂不支持极速预览。


暂不支持setTimeOut。




工程目录

图片

新建流程

选择静态服务窗口

图片

选择项目模板

图片

设置卡片名称、简介、模块大小等

图片

根据选择的样板,自动添加卡片项目相关文件

图片

默认的预览视图

图片

卡片事件(静态卡片)

需要使用FromLink容器来实现服务卡片和App之间的交互,支持router、message和call三种类型的事件。


    
        
        参数名
        
        
        参数类型
        
        
        必填
        
        
        参数描述
        
    
    
        
        action
        
        
        string
        
        
        是
        
        
        action的类型,支持三种预定义的类型:

        - router:跳转到提供方应用的指定UIAbility。

        - message:自定义消息,触发后会调用提供方FormExtensionAbility的onFormEvent()生命周期回调。

        - call:后台启动提供方应用。触发后会拉起提供方应用的指定UIAbility(仅支持launchType为singleton的UIAbility,即启动模式为单实例的UIAbility),但不会调度到前台。提供方应用需要具备后台运行权限(ohos.permission.KEEP_BACKGROUND_RUNNING)。

        说明:

        不推荐使用router事件刷新卡片UI。
        
    
    
        
        moduleName
        
        
        string
        
        
        否
        
        
        action为router / call 类型时跳转的模块名。
        
    
    
        
        bundleName
        
        
        string
        
        
        否
        
        
        action为router / call 类型时跳转的包名。
        
    
    
        
        abilityName
        
        
        string
        
        
        否
        
        
        action为router / call 类型时跳转的UIAbility名。
        
    
    
        
        uri

        
        
        
        string
        
        
        否
        
        
        action为router 类型时跳转的UIAbility的统一资源标识符。uri和abilityName同时存在时,abilityName优先。
        
    
    
        
        params
        
        
        Object
        
        
        否
        
        
        当前action携带的额外参数,内容使用JSON格式的键值对形式。call 类型时需填入参数'method',且类型需要为string类型,用于触发UIAbility中对应的方法。

        说明:

        不推荐通过params传递卡片内部的状态变量。
        
    


案例代码 

实现效果

图片

项目架构

图片

DateUtil.ets

export class DateUtil {
/**

  • 返回时间
  • @param date
  • @returns 14:53样式的时间
    */

static ToTime(date: Date): string {

if (date == null) {
  return "";
}
return `${DateUtil.PrefixInteger(date.getHours(), 2)}:${DateUtil.PrefixInteger(date.getMinutes(), 2)}`

}

/**

  • 返回月份和周几
  • @param date
  • @returns 返回6月17日(周一)的样式
    */

static ToMonthDay(date: Date): string {

if (date == null) {
  return "";
}
const weekDays = ["周日", "周一", "周二", "周三", "周四", "周五", "周六"]
return `${date.getMonth() + 1}月${date.getDate()}日(${weekDays[date.getDay()]})`

}

static PrefixInteger(num: number, length: number) {

return (Array(length).join('0') + num).slice(-length);

}
}

图片

Ticket_WidgetCard.ets

import { TicketShow_ViewModel } from '../viewmodel/TicketShow_ViewModel'
import { TicketShow_View } from '../view/TicketShow_view'

@Entry
@Component
struct Ticket_WidgetCard {
/*

  • action的类型
    */

readonly ACTION_TYPE: string = 'router';
/*

  • action为router / call 类型时跳转的UIAbility名
    */

readonly ABILITY_NAME: string = 'EntryAbility';
/*

  • The message.
    */

readonly MESSAGE: string = 'add detail';
/*

  • The height percentage setting.
    */

readonly FULL_HEIGHT_PERCENT: string = '100%';
@State ticketShowVM: TicketShow_ViewModel = new TicketShow_ViewModel(

"G6357",
new Date(2024, 5, 17, 14, 33),
new Date(2024, 5, 17, 20, 0),
"凤凰古城",
"广州",
"二等车 06车 05F号");

build() {

FormLink({
  action: this.ACTION_TYPE,
  abilityName: this.ABILITY_NAME,
  params: {
    message: this.MESSAGE
  }
}) {
  Stack({ alignContent: Alignment.BottomEnd }) {
    TicketShow_View({
      viewModel: this.ticketShowVM
    })
      .margin(10)
    Image($r('app.media.railway'))
      .height(80)
      .opacity(0.3)
      .margin({ bottom: 10, right: 20 })
  }
  .height(this.FULL_HEIGHT_PERCENT)
  .width("100%")
  .backgroundColor('#00000000')
  .linearGradient({
    angle: 90,
    colors: [["#1f82ca", 0.0], ["#24c8df", 1.0]]
  })
}

}
}

图片

TicketShow_view.ets

import { DateUtil } from '../../common/DateUtil';
import { TicketShow_ViewModel, TicketStage } from '../viewmodel/TicketShow_ViewModel'

@Component
export struct TicketShow_View {
@ObjectLink viewModel: TicketShow_ViewModel
/**

  • 字体颜色
    */

readonly TEXT_COLOR: ResourceColor = Color.White;

build() {

Column() {
  Row() {
    Column() {
      Text(DateUtil.ToTime(this.viewModel.BoardingTime))
        .fontSize(20)
        .fontWeight(FontWeight.Bold)
        .fontColor(this.TEXT_COLOR)

      Text(this.viewModel.BoardingAddress)
        .fontSize(14)
        .margin({ top: 5 })
        .fontColor(this.TEXT_COLOR)
    }
    .height("100%")
    .layoutWeight(1)
    .alignItems(HorizontalAlign.Start)
    .justifyContent(FlexAlign.Start)

    Column() {
      Text(this.viewModel.Id)
        .fontSize(14)
        .fontColor(this.TEXT_COLOR)
      Path()
        .commands('M0 0 L300 0 L270 -10 L270 0 Z')
        .margin({ top: 4 })
        .strokeWidth(1)
        .fill(this.TEXT_COLOR)
        .stroke(this.TEXT_COLOR)
      Text(DateUtil.ToMonthDay(this.viewModel.BoardingTime))
        .fontSize(12)
        .margin({ top: 5 })
        .fontColor(this.TEXT_COLOR)
    }
    .height("100%")
    .layoutWeight(2)
    .justifyContent(FlexAlign.Start)

    Column() {
      Text(DateUtil.ToTime(this.viewModel.ArrivalTime))
        .fontSize(20)
        .fontWeight(FontWeight.Bold)
        .fontColor(this.TEXT_COLOR)
      Text(this.viewModel.ArrivalAddress)
        .fontSize(14)
        .margin({ top: 5 })
        .fontColor(this.TEXT_COLOR)
    }
    .height("100%")
    .layoutWeight(1)
    .alignItems(HorizontalAlign.End)
    .justifyContent(FlexAlign.Start)
  }
  .width("100%")
  .layoutWeight(2)
  .margin({ top: 20 })

  Column() {
    Text(this.viewModel.Position)
      .fontSize(12)
      .fontColor(this.TEXT_COLOR)
    Row() {
      Text("状态:")
        .fontSize(12)
        .fontColor(this.TEXT_COLOR)
      Text(TicketStage[this.viewModel.Stage])
        .fontSize(12)
        .fontColor(this.TEXT_COLOR)
    }
    .margin({ top: 5 })
  }
  .width("100%")
  .layoutWeight(1)
  .alignItems(HorizontalAlign.Start)
  .justifyContent(FlexAlign.Start)
}
.width("100%")
.height("100%")

}
}

图片

TicketShow_ViewModel.ets

/**

  • 展示组件的ViewModel
    */

@Observed
export class TicketShow_ViewModel {
/**

  • 火车编号
    */

public Id: string = '';
/**

  • 开始时间
    */

public BoardingTime: Date = new Date();
/**

  • 到达时间
    */

public ArrivalTime: Date = new Date();
/**

  • 起始站
    */

public BoardingAddress: string = "";
/**

  • 终点站
    */

public ArrivalAddress: string = "";
/**

  • 座位
    */

public Position: string = "";
/**

  • 状态
    */

public Stage: TicketStage = TicketStage.待车

constructor(

id: string,
boardingTime: Date,
arrivalTime: Date,
boardingAddress: string,
arrivalAddress: string,
position: string) {
this.Id = id;
this.BoardingTime = boardingTime;
this.BoardingAddress = boardingAddress;
this.ArrivalTime = arrivalTime;
this.ArrivalAddress = arrivalAddress;
this.Position = position;

}

public isDraft(): boolean {

return true;

}
}

/**

  • 车票状态
    */

export enum TicketStage {
待车,
正在检票,
停止检票
}

图片

注意

里面的图片是需要自己去下载的,暂未实现数据和程序联动


奥尼ᴮᴵᴹᵉʳ
1 声望1 粉丝