【HarmonyOS Next开发】静态服务卡片

2024-12-24 23:05:14
9次阅读
0个评论

简介

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

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

不支持功能

  • 不支持导入共享包。
  • 不支持native语言,仅支持声明式范式的部分组件、事件、动效、数据管理、状态管理和API能力。
  • 暂不支持极速预览。
  • 暂不支持setTimeOut。

工程目录

cke_1474.png

新建流程

选择静态服务窗口

image.png

选择项目模板

image.png

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

image.png

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

image.png

默认的预览视图

image.png

卡片事件(静态卡片)

需要使用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传递卡片内部的状态变量。

案例代码 

实现效果

cke_40621.png

项目架构

cke_57642.png

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 {
  待车,
  正在检票,
  停止检票
}

注意

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

收藏00

登录 后评论。没有帐号? 注册 一个。