【每日学点HarmonyOS Next知识】类型判断、刘海高度、隐私弹窗、滑动下一页效果、清楚缓存

1、HarmonyOS instanceof判断错误?

ArkTS部分支持instanceof,可参考文档:https://developer.huawei.com/consumer/cn/doc/harmonyos-guides-V5/typescript-to-arkts-migration-guide-V5

instanceof运算符在传递的过程中可能会发生以下情况:对象的属性在传递的过程中被修改。对象的引用在传递的过程中被改变。对象的构造函数可能尚未完成执行,导致对象状态不完整。以上情况都可能导致在接收线程中使用instanceof进行类型判断时出现错误。因此,直接依赖instanceof进行类型判断不够安全。

2、HarmonyOS 下刘海的高宽获取不到?

通过 window.getWindowAvoidArea(window.AvoidAreaType.TYPE_CUTOUT) 获取刘海的高宽的时候,没有取到下刘海的数据。

获取导航栏高度,设置window.AvoidAreaType.TYPE_NAVIGATION_INDICATOR

3、HarmonyOS 有没有隐私政策弹框的demo?

可以使用Stack组件模拟实现Dialog的效果,页面跳转之后返回 可以做到 Dialog依然显示的效果

复制代码
import router from '@ohos.router';

@Entry
@Component
struct First {
  @State textValue: string = 'Hello World'
  // 显隐控制设置为不占用
  @State visible: Visibility = Visibility.None
  @State path: string = "pages/Index"

  build() {
    // 使用stack可以实现假的dialog覆盖原页面上面
    Stack() {
      Row() {
        // 初始页面
        Column() {
          Text('Hello World')
            .fontSize(50)
            .fontWeight(FontWeight.Bold)
          // 触发dialog的地方
          Button('click')
            .onClick(() => {
              //用于检测点击事件是否透传到原来的页面,我测了一下是没有透传的,符合dialog规范
              console.log("hit me!")
              if (this.visible == Visibility.Visible) {
                this.visible = Visibility.None
              } else {
                this.visible = Visibility.Visible
              }
            })
            .backgroundColor(0x777474)
            .fontColor(0x000000)
        }
        .width('100%')
      }
      .height('100%')
      .backgroundColor(0x885555)

      //这里开始是构造弹窗效果主要需要修改的地方,首先是加了一个半透明灰色的蒙层效果
      Text('')
        .onClick(() => {
          if (this.visible == Visibility.Visible) {
            this.visible = Visibility.None
          } else {
            this.visible = Visibility.Visible
          }
        })
        .width('100%')
        .height('100%')// 透明度可以自己调节一下
        .opacity(0.16)
        .backgroundColor(0x000000)
        .visibility(this.visible)
      Column() {
        // 这个可以调节对话框效果,栅格布局,xs,sm,md,lg分别为四种规格
        // 下面的breakpoints是用来区别当前属于哪个类型的断点
        // gridRow里的栅格数量为总数,gridCol里的就是偏移和假Dialog所占据的栅格数
        GridRow({
          columns: {
            xs: 1,
            sm: 4,
            md: 8,
            lg: 12
          },
          breakpoints: {
            value: ["400vp", "600vp", "800vp"],
            reference: BreakpointsReference.WindowSize
          },
        }) {
          GridCol({
            span: {
              xs: 1,
              sm: 2,
              md: 4,
              lg: 8
            },
            offset: {
              xs: 0,
              sm: 1,
              md: 2,
              lg: 2
            }
          }) {
            // 这里放的就是原Dialog里的column里的东西,稍微改改应该就可以用了
            Column() {
              Text('Change text').fontSize(20).margin({ top: 10, bottom: 10 })
              TextInput({ placeholder: '', text: this.textValue }).height(60).width('90%')
                .onChange((value: string) => {
                  this.textValue = value
                })
              Text('Whether to change a text?').fontSize(16).margin({ bottom: 10 })
              Flex({ justifyContent: FlexAlign.SpaceAround }) {
                Button('cancel')
                  .onClick(() => {
                    if (this.visible == Visibility.Visible) {
                      this.visible = Visibility.None
                    } else {
                      this.visible = Visibility.Visible
                    }
                  }).backgroundColor(0xffffff).fontColor(Color.Black)
                Button('jump')
                  .onClick(() => {
                    router.pushUrl({
                      //url: 'pages/Index'
                      url: this.path
                    })
                  }).backgroundColor(0xffffff).fontColor(Color.Red)
              }.margin({ bottom: 10 })
            }
            .backgroundColor(0xffffff)
            .visibility(this.visible)
            .clip(true)
            .borderRadius(20)
          }
        }
      }.width('95%') //设置弹窗宽度
    }
  }
}
4、HarmonyOS 滑动下一页效果应该如何做?

参考代码:

复制代码
@Entry
@Component
struct NovelPage {
  @Provide('fontSize') @Watch('onFontSizeChange') fontSize: number = Constants.INIT_FONT_SIZE;
  @Provide('bgColorIndex') @Watch('onBgColorChanged') bgColorIndex: BGColorType = BGColorType.WHITE;
  @Provide('bgColor') bgColor: string = BG_COLOR_ARRAY[BGColorType.WHITE];
  @Provide('offsetX') offsetX: number = 0
  @Provide('offsetY') offsetY: number = 0;
  @Provide('screenH') screenH: number = 0;
  @Provide('screenW') screenW: number = 0;
  @Provide('sumRow') sumRow: number = 0;
  @Provide('rowWord') rowWord: number = 0;
  @Provide('rotateAngleOne') rotateAngleOne: number = Constants.INIT_ROTATE_ANGLE_ONE;
  @Provide('rotateAngleTwo') rotateAngleTwo: number = 0.0;
  @Provide('curPosition') curPosition: number = 0;
  @Provide('turnStyle') turnStyle: FlipPageType = FlipPageType.SLIDE_FLIP_PAGE;
  @Provide('currentPageNum') @Watch('onFlush') currentPageNum: number = 1;
  @Provide('pageWordSum') pageWordSum: number = 0;
  @Provide('light') light: number = Constants.INIT_SCREEN_LIGHT;
  @Provide('isSystemLight') isSystemLight: boolean = false;
  @Provide('rowGap') rowGap: number = Constants.INIT_ROW_GAP;
  @State currentStartIndex: number = 0;
  @State isShow: boolean = false;
  @State isFontChanged: boolean = false;

  aboutToAppear(): void {
    this.screenW = px2vp(display.getDefaultDisplaySync().width);
    this.screenH = px2vp(display.getDefaultDisplaySync().height - (AppStorage.get('avoidHeight') as number));
    this.sumRow = Math.floor((this.screenH) / (this.fontSize + this.rowGap));
    this.rowWord = Math.floor((this.screenW - Constants.SCREEN_MARGIN_LEFT * 2) / this.fontSize);
    this.simulatePageContent();
    this.changeSystemBarStatue();
  }

  onFontSizeChange() {
    this.sumRow = Math.floor((this.screenH) / (this.fontSize + this.rowGap));
    this.rowWord = Math.floor((this.screenW - Constants.SCREEN_MARGIN_LEFT * 2) / this.fontSize);
    let pageWordSum = this.sumRow * this.rowWord;

    if (this.currentStartIndex > pageWordSum) {
      this.currentPageNum = Math.floor(this.currentStartIndex / (pageWordSum)) +
        (this.currentStartIndex > 1 && this.currentStartIndex % pageWordSum > 0 ? 2 : 1);
    } else if (this.currentStartIndex > 0) {
      this.currentPageNum = 2;
    } else {
      Logger.info('currentStartIndex = ' + this.currentStartIndex);
    }
    this.isFontChanged = true;
    this.simulatePageContent();
  }

  changeSystemBarStatue(): void {
    window.getLastWindow(getContext(this), (err, data) => {
      const errCode = err.code;
      if (errCode) {
        return;
      }
      let SystemBarProperties: window.SystemBarProperties = {
        statusBarColor: BG_COLOR_ARRAY[this.bgColorIndex],
        navigationBarColor: BG_COLOR_ARRAY[this.bgColorIndex],
        navigationBarContentColor: Constants.TRANSPARENT
      };
      try {
        data.setWindowSystemBarProperties(SystemBarProperties, (err: BusinessError) => {
          const errCode: number = err.code;
          if (errCode) {
            Logger.error('Failed to set the system bar properties. Cause: ' + JSON.stringify(err));
            return;
          }
          data.setWindowBackgroundColor(BG_COLOR_ARRAY[this.bgColorIndex]);
        });
      } catch (exception) {
        Logger.error('Failed to set the system bar properties. Cause: ' + JSON.stringify(exception));
      }
    });
  }

  onBgColorChanged() {
    this.changeSystemBarStatue();
  }

  onFlush() {
    Logger.info('currentPageNum=' + this.currentPageNum + ', isFontChanged=' + this.isFontChanged);
    if (this.isFontChanged && this.currentPageNum === 1) {
      this.isFontChanged = false;
      this.currentStartIndex = 0;
    }
  }

  simulatePageContent() {
    this.offsetY = 0;
    this.rotateAngleTwo = 0.0;
    this.rotateAngleOne = Constants.INIT_ROTATE_ANGLE_ONE;
  }

  private clickAnimateTo(isLeft: Boolean) {
    if (this.turnStyle === FlipPageType.SLIDE_FLIP_PAGE) {
      animateTo({
        duration: Constants.SLIDE_DURATION,
        curve: Curve.EaseOut,
        onFinish: () => {
          if (this.offsetX > 0) {
            this.currentPageNum > 0 ? this.currentPageNum - 1 : this.currentPageNum;
            this.currentStartIndex -= this.sumRow * this.rowWord;
          }
          if (this.offsetX < 0) {
            this.currentPageNum += 1;
            this.currentStartIndex += this.sumRow * this.rowWord;
          }
          Logger.info(this.currentStartIndex.toString());
          this.offsetX = 0;
          this.simulatePageContent();
        }
      }, () => {
        if (isLeft) {
          this.offsetX = this.screenW;
        } else {
          this.offsetX = -this.screenW;
        }
      })
    }
  }

  build() {
    Row() {

      if (this.turnStyle === FlipPageType.SLIDE_FLIP_PAGE) {
        SlideFlipView({
          currentStartIndex: this.currentStartIndex
        })
      }

    }

    .width(Constants.FULL_PERCENT)
    .height(Constants.FULL_PERCENT)
    .bindSheet(
      $$this.isShow,
      this.myBuilder(),
      {
        height: SheetSize.FIT_CONTENT,
        detents: [Constants.SHEET_HEIGHT, Constants.SHEET_HEIGHT + 1],
        showClose: true,
        dragBar: true,
        title: { title: Constants.SHEET_TITLE },
        backgroundColor: Constants.SHEET_BACKGROUND_COLOR
      }
    )
    .backgroundColor(this.bgColor)
  }

  @Builder
  myBuilder() {


  }
}

@Component
export default struct Reader {
  @Consume('bgColor') @Watch('onPageChange') bgColor: string;
  @Consume('fontSize') @Watch('onPageChange') fontSize: number;
  @Consume('turnStyle') turnStyle: FlipPageType;
  @Consume('screenW') screenW: number;
  @Consume('screenH') screenH: number;
  @Consume('rowGap') rowGap: number;
  @Consume('sumRow') sumRow: number
  @Consume('rowWord') rowWord: number;
  @Prop @Watch('onPageChange') startIndex: number = 0;
  private settings: RenderingContextSettings = new RenderingContextSettings(true);
  private context: CanvasRenderingContext2D = new CanvasRenderingContext2D(this.settings);
  private wordWidth: number = 0;
  private wordHeight: number = 0;

  aboutToAppear(): void {
    this.drawText(this.startIndex);
  }

  onPageChange() {
    this.drawText(this.startIndex);
  }

  drawText(startIndex: number) {
    this.wordWidth = this.fontSize;
    this.wordHeight = this.fontSize;
    this.context.fillStyle = this.bgColor;
    this.context.fillRect(0, 0, this.screenW, this.screenH);
    this.context.fillStyle = Color.Black;
    this.context.font = vp2px(this.fontSize) + Constants.CANVAS_FONT_SET;
    if (startIndex < 0) {
      startIndex = 0;
    }

    let gap = ((this.screenW - Constants.SCREEN_MARGIN_LEFT * 2) - this.wordWidth * this.rowWord) / (this.rowWord - 1);
    let realRowGap = (this.screenH - this.sumRow * (this.wordHeight + this.rowGap)) / (this.sumRow - 1);
    let currentX = Constants.SCREEN_MARGIN_LEFT;
    let currentY = this.wordHeight;
    for (let i = startIndex;; i++) {
      if (currentX + this.wordWidth > this.screenW - (Constants.SCREEN_MARGIN_LEFT - 1)) {
        currentX = Constants.SCREEN_MARGIN_LEFT;
        currentY = currentY + this.rowGap + this.wordHeight + realRowGap;
        if (currentY > this.screenH) {
          break;
        }
      }
      this.context.fillText(Constants.TEXT.charAt(i % Constants.TEXT.length), currentX, currentY);
      currentX += this.wordWidth + gap;
    }
  }

  build() {
    Flex({ direction: FlexDirection.Row, alignItems: ItemAlign.Start, justifyContent: FlexAlign.Start }) {
      Column() {
        Canvas(this.context)
          .width(Constants.FULL_PERCENT)
          .height(Constants.FULL_PERCENT)
          .onReady(() => {
            this.drawText(this.startIndex);
          })
      }
      .width(Constants.FULL_PERCENT)
    }
    .height(Constants.FULL_PERCENT)
  }
}

@Component
export struct SlideFlipView {
  @Consume('offsetX') offsetX: number;
  @Consume('sumRow') sumRow: number;
  @Consume('rowWord') rowWord: number;
  @Consume('screenW') screenW: number;
  @Consume('currentPageNum') currentPageNum: number;
  @Link currentStartIndex: number;
  private isFirst: boolean = false;

  build() {
    Stack() {
      Reader({ startIndex: this.currentStartIndex + this.sumRow * this.rowWord })
        .translate({ x: this.offsetX >= 0 ? this.screenW : this.screenW + this.offsetX, y: 0, z: 0 })

      Reader({ startIndex: this.currentStartIndex })
        .translate({ x: this.offsetX, y: 0, z: 0 })
        .width(this.screenW)

      Reader({ startIndex: this.currentStartIndex - this.sumRow * this.rowWord })
        .translate({ x: this.offsetX >= 0 ? -this.screenW + this.offsetX : -this.screenW, y: 0, z: 0 })
    }
    .gesture(
      PanGesture()
        .onActionUpdate((event?: GestureEvent) => {
          if (!event) {
            return;
          }
          if (this.currentPageNum <= 1 && event.offsetX > 0) {
            this.isFirst = true;
            return;
          }

          this.offsetX = event.offsetX;
        })
        .onActionEnd(() => {
          animateTo({
            duration: Constants.FLIP_DURATION,
            curve: Curve.EaseOut,
            onFinish: () => {
              if (this.offsetX > 0) {
                this.currentPageNum -= 1;
                if (this.currentStartIndex !== 0) {
                  this.currentStartIndex -= this.sumRow * this.rowWord;
                }
              }
              if (this.offsetX < 0) {
                this.currentPageNum += 1;
                this.currentStartIndex += this.sumRow * this.rowWord;
              }
              if (this.isFirst) {
                promptAction.showToast({
                  message: Constants.MSG_FLIP_OVER,
                  duration: Constants.PROMPT_DURATION
                });
                this.isFirst = false;
              }
              this.offsetX = 0;
            }
          }, () => {
            if (this.offsetX > 0) {
              this.offsetX = this.screenW;
            }
            if (this.offsetX < 0) {
              this.offsetX = -this.screenW;
            }
          })
        })
    )
  }
}
5、HarmonyOS 清除缓存功能?

app中有清除缓存的需求功能,清除缓存和计算app内缓存大小需要怎么实现。

查询缓存用storageStatistics.getCurrentBundleStats()接口,清除文件缓存,需要调用context的cacheDir获取缓存,然后调用系统文件fs接口,判断是文件或者文件夹,再分别消除缓存https://developer.huawei.com/consumer/cn/doc/harmonyos-references-V5/js-apis-file-storage-statistics-V5#storagestatisticsgetcurrentbundlestats9 清理:

复制代码
import fs from '@ohos.file.fs';
let cacheDir = context.cacheDir;
@Entry
@Component
struct Clear_cache {
  clearCache() {
    // let cacheDir = getContext(this).cacheDir
    // fs.rmdirSync(cacheDir)
    // console.log("delete !!!")

    fs.listFile(cacheDir).then((filenames) => {
      for (let i = 0;i < filenames.length; i++) {
        // let dirPath = cacheDir+filenames[i]
        let dirPath = ${cacheDir}/${filenames[i]}
        // 判断是否文件夹
        let isDirectory
        try {
          isDirectory = fs.statSync(dirPath).isDirectory()
        }
        catch (e) {
          console.log(e)
        }

        if (isDirectory) {
          fs.rmdirSync(dirPath)
        } else {
          fs.unlink(dirPath).then(() => {
            console.info("remove file succeed");
          }).catch((err) => {
            console.info("remove file failed with error message: " + err.message + ", error code: " + err.code);
          });
        }
      }

    })
  }
}
相关推荐
嗝o゚1 小时前
鸿蒙智慧屏与Flutter适配:无硬件功能的兼容处理
flutter·华为·开源·harmonyos
luxy20041 小时前
HarmonyOS简易时钟应用
华为·harmonyos
俩毛豆3 小时前
基于HarmonyOS(NEXT)的超级App中的搜索架构实现(直播文字干货版)
成长·架构·app·harmonyos·搜索
嗝o゚3 小时前
Flutter 无障碍功能开发最佳实践
python·flutter·华为
嗝o゚4 小时前
开源鸿蒙 Flutter 应用包瘦身实战
flutter·华为·开源·harmonyos
力江4 小时前
FastAPI 最佳架构实践,从混乱到优雅的进化之路
python·缓存·架构·单元测试·fastapi·分页·企业
屋外雨大,惊蛰出没5 小时前
小白安装Redis
数据库·redis·缓存
云和数据.ChenGuang5 小时前
鸿蒙负一屏的技术定位与核心价值
华为·wpf·harmonyos
遇到困难睡大觉哈哈8 小时前
HarmonyOS 关系型数据库 RDB 数据持久化(ArkTS)实战:建库建表、CRUD、事务、FTS、性能优化,一篇搞懂
笔记·华为·harmonyos
Maiko Star8 小时前
基于Redis ZSet实现多维度题目贡献度排行榜
数据库·redis·缓存