【每日学点鸿蒙知识】Hap 安装失败、ArkTS 与C++ 数组转换、渐变遮罩效果等

1、在启动调试或运行应用/服务时,安装HAP出现错误,提示"error: install failed due to older sdk version in the device"错误信息。

这是由于编译打包所使用的SDK版本与设备镜像版本不匹配。不匹配的场景包括:

场景一:设备上的镜像版本低于编译打包的SDK版本,请更新设备镜像版本。查询设备镜像版本命令:

hdc shell param get const.ohos.apiversion

如果镜像提供的api版本为10,且应用编译所使用的SDK版本也为10,仍出现该报错,可能是由于镜像版本较低,未兼容新版本SDK校验规则,请将镜像版本更新为最新版本。

场景二:对于需要运行在OpenHarmony设备上的应用,请确认runtimeOS已改为OpenHarmony。

2、在启动调试或运行应用/服务时,安装HAP出现错误,提示"error: install sign info inconsistent"错误信息。

这由于设备上已安装的应用与新安装的应用中签名不一致。如果在Edit Configurations中勾选了"Keep Application Data"(不卸载应用,覆盖安装),并且重新进行了签名,将导致该报错。

卸载设备上已安装的应用,或取消勾选"Keep Application Data"后,重新安装新的应用。

3、如何实现RichEditor和Component成为一个整体?

RichEditor上面有个Component,现在希望RichEditor和Component成为一个整体,能够自适应光标位置进行滚动,应该如何实现,目前用Scroller无法获取RichEditor中光标的具体坐标(光标基于RichEditor的x和y位置),无法实现滚动。

可以用Scroll将RichEditor和Component包裹,通过onAreaChange的回调,调用scroller.scrollBy的能力,以此来改变滚动组件的高度。

可以参考代码:

@Entry
@Component
struct Index {
  editorController = new RichEditorController()
  scroller: Scroller = new Scroller()

  build() {
    Column() {
      Scroll(this.scroller) {
        Column() {
          Image($r('app.media.startIcon'))
            .width('100%')
            .height(200)
            .margin({ bottom: 20 })
          RichEditor({ controller: this.editorController })
            .id('RichEditor')
            .width('100%')
            .backgroundColor(Color.Yellow)
            .onReady(() => {
              this.editorController.addImageSpan($r("app.media.startIcon"),
                {
                  imageStyle:
                  {
                    size: ["100px", "100px"]
                  }
                })
              this.editorController.addTextSpan('男生女生向前冲',
                {
                  style:
                  {
                    fontColor: Color.Blue,
                    fontSize: 30
                  }
                })
            })
            .onAreaChange((_, value) => {
              if (_.height !== value.height) {
                this.scroller.scrollBy(0, Number(value.height) - 200)
              }
            })
          Button('getSpans-文字').onClick((event: ClickEvent) => {
            let getSpans = this.editorController.getSpans({ start: 0 })
            // 必须进行强转才能获取文字信息或者图片信息
            let span0 = getSpans[0] as RichEditorTextSpanResult
          })
          Button('getSpans-图片').onClick((event: ClickEvent) => {
            let getSpans = this.editorController.getSpans({ start: 0 })
            let span1 = getSpans[1] as RichEditorImageSpanResult
          })
          Button('RichEditor获焦').onClick(() => {
            focusControl.requestFocus('RichEditor')
          })
        }
      }
      .scrollable(ScrollDirection.Vertical) // 滚动方向纵向
      .scrollBar(BarState.On) // 滚动条常驻显示
      .scrollBarColor(Color.Gray) // 滚动条颜色
    }
  }
}

4、如何实现ArkTS与C/C++的数组转换?

TS2NAPI

TS侧代码:

Button("TS2NAPI")
  .fontSize(50)
  .fontWeight(FontWeight.Bold)
  .onClick(() => {
    let napiArray: Int32Array = new Int32Array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
    console.info("TS2NAPI: JS   " + napiArray)
    testNapi.TS2NAPI(napiArray)
  })

NAPI侧代码:

// TS array 传到NAPI层
static napi_value TS2NAPI(napi_env env, napi_callback_info info) {
  // 获取TS层传来的参数
  size_t argc = 1;
  napi_value args;
  napi_get_cb_info(env, info, &argc, &args, NULL, NULL);
  napi_value input_array = args;

  // 获取传入数组typedarray生成input_buffer
  napi_typedarray_type type; // 数据类型
  napi_value input_buffer;
  size_t byte_offset; // 数据偏移
  size_t i, length;   // 数据字节大小
  napi_get_typedarray_info(env, input_array, &type, &length, NULL, &input_buffer, &byte_offset);

  // 获取数组数据
  void *data;
  size_t byte_length;
  napi_get_arraybuffer_info(env, input_buffer, &data, &byte_length);

  if (type == napi_int32_array) {
    int32_t *data_bytes = (int32_t *)(data);
    int32_t num = length / sizeof(int32_t);

    string str = "";
    for (int32_t i = 0; i < num; i++) {
      int32_t tmp = *((int32_t *)(data_bytes) + i);
      str += (to_string(tmp) + ' ');
    }
    OH_LOG_INFO(LOG_APP, "TS2NAPI: C++  %{public}s", str.c_str());
  }

  return NULL;
}

NAPI2TS

TS侧代码:

Button("NAPI2TS")
  .fontSize(50)
  .fontWeight(FontWeight.Bold)
  .onClick(() => {
    let napiArray: Int32Array = testNapi.NAPI2TS()
    console.info("NAPI2TS: JS   " + napiArray)
  })

NAPI侧代码:

// NAPI层 array 传到TS层
static napi_value NAPI2TS(napi_env env, napi_callback_info info) {
  // 数据个数
  int num = 10;

  // 创建output_buffer
  napi_value output_buffer;
  void *output_ptr = NULL;
  napi_create_arraybuffer(env, num * sizeof(int32_t), &output_ptr, &output_buffer);

  // output_array
  napi_value output_array;
  napi_create_typedarray(env, napi_int32_array, num, output_buffer, 0, &output_array);

  // 给output_ptr、output_buffer赋值
  int32_t *output_bytes = (int32_t *)output_ptr;
  for (int32_t i = 0; i < num; i++) {
    output_bytes[i] = i;
  }

  string str = "";
  for (int32_t i = 0; i < num; i++) {
    int32_t tmp = *((int32_t *)(output_ptr) + i);
    str += (to_string(tmp) + ' ');
  }
  OH_LOG_INFO(LOG_APP, "NAPI2TS: C++  %{public}s", str.c_str());

  return output_array;
}

实用场景:

ArkTS侧读取rawfile的图片,传递到NAPI侧进行处理,然后传回ArkTS进行展示:

Button("Test")
  .fontSize(50)
  .fontWeight(FontWeight.Bold)
  .onClick(() => {

    getContext().resourceManager.getRawFileContent('test.png').then(value => {
      hilog.info(0x0000, 'getRawFileContent', '%{public}s', 'OK');
      const fileData: Uint8Array = value;
      // 获取图片的ArrayBuffer
      let buffer = fileData.buffer;

      let input = new Uint8Array(buffer)
      let output = testNapi.TEST(input);

      let decodingOptions: image.DecodingOptions = {
        editable: true,
        desiredPixelFormat: 3,
      }
      let imageSource = image.createImageSource(output.buffer);
      imageSource.createPixelMap(decodingOptions).then(map => {
        this.imageSrc = map;
      })
    }).catch((err: BusinessError) => {
      hilog.error(0x0000, 'getRawFileContent', '%{public}s', err.message);
    })
  })

Image(this.imageSrc)
  .height(100)
  .width(100)

5、如何实现顶部渐变遮罩效果?

直播间的弹幕列表顶部需要渐变遮罩效果,如何实现呢?

使用overlay通过属性linearGradient同时使用blendMode让当前浮层与下方list混合实现渐变遮罩效果。

效果图如下:

参考代码:

@Entry
@Component
struct Index {
  private arr: number[] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

  @Builder
  overlayBuilder() {
    Stack()
      .height("100%")
      .width("100%")
      .linearGradient({
        direction: GradientDirection.Bottom, // 渐变方向
        colors: [["#00FFFFFF", 0.0], ["#FFFFFFFF", 0.3]] // 数组末尾元素占比小于1时满足重复着色效果
      })
      .blendMode(BlendMode.DST_IN, BlendApplyType.OFFSCREEN)
      .hitTestBehavior(HitTestMode.None)
  }

  build() {
    Column() {
      List({ space: 20, initialIndex: 0 }) {
        ForEach(this.arr, (item: number) => {
          ListItem() {
            Text('' + item)
              .width('100%')
              .height(100)
              .fontSize(16)
              .textAlign(TextAlign.Center)
              .borderRadius(10)
              .backgroundColor(0xFFFFFF)
          }
          .onClick(() => {
            console.log('is click')
          })
        }, (item: string) => item)
      }.width('90%')
      .scrollBar(BarState.Off)
      .overlay(this.overlayBuilder())
      .blendMode(BlendMode.SRC_OVER, BlendApplyType.OFFSCREEN)
    }.width('100%').height('100%').backgroundColor(0xDCDCDC).padding({ top: 5 })
  }
}
相关推荐
我搞slam16 分钟前
全覆盖路径规划算法之BCD源码实现(The Boustrophedon Cellular Decomposition)
c++·算法·图搜索算法
Rossy Yan21 分钟前
【C++数据结构——查找】二分查找(头歌实践教学平台习题)【合集】
开发语言·数据结构·c++·算法·查找·头歌实践教学平台·合集
zhgjx_chen1 小时前
ENSP综合实验(中小型网络)
服务器·网络·华为
塞尔维亚大汉1 小时前
移植案例与原理 - startup子系统之bootstrap_lite服务启动引导部件(1)
harmonyos
埃菲尔铁塔_CV算法2 小时前
BOOST 在计算机视觉方面的应用及具体代码分析(二)
c++·人工智能·算法·机器学习·计算机视觉
跳河轻生的鱼4 小时前
海思Linux(一)-Hi3516CV610的开发-ubuntu22_04环境创建
linux·单片机·学习·华为
mit6.8247 小时前
[Qt] 信号和槽(2) | 多对多 | disconnect | 结合lambda | sum
linux·前端·c++·qt·学习
gonghw4037 小时前
Linux开机LOGO更换以及附带问题
linux·c++
轻口味7 小时前
【每日学点鸿蒙知识】跳转三方地图、getStringSync性能、键盘避让模式等
华为·harmonyos
儿歌八万首7 小时前
鸿蒙ArkUI实现部门树列表
华为·harmonyos·鸿蒙·arkui